简体   繁体   中英

Replacing Column Name with Loop in R

I have three df P1,P2,P3 with each three columns. I want to change the second column from each df to D1, D2, D3 with a loop but nothing is working. What do I miss out?

C1 <- c(12,34,22)
C2 <- c(43,86,82)
C3 <- c(98,76,25)

C4 <- c(12,34,22)
C5 <- c(43,86,82)
C6 <- c(98,76,25)

C7 <- c(12,34,22)
C8 <- c(43,86,82)
C9 <- c(98,76,25)

P1 <- data.frame(C1,C2,C3)
P2 <- data.frame(C4,C5,C6)
P3 <- data.frame(C7,C8,C9)

x <- c("P1", "P2", "P3")
b <- c("D1","D2","D3")

for (V in b){
  names(x)[2] <- "V"
}

The output I would expect is:

P1 <- data.frame(C1,D1,C3)
P2 <- data.frame(C4,D2,C6)
P3 <- data.frame(C7,D3,C9)

We can use mget to get the values of the string vector in a list , use Map to rename the second column each of the list element with the corresponding 'b' value, then use list2env to update those objects in the global env

list2env(Map(function(x, y) {names(x)[2] <- y; x}, mget(x), b), .GlobalEnv)

-output

P1
#  C1 D1 C3
#1 12 43 98
#2 34 86 76
#3 22 82 25

P2
#  C4 D2 C6
#1 12 43 98
#2 34 86 76
#3 22 82 25
P3
#  C7 D3 C9
#1 12 43 98
#2 34 86 76
#3 22 82 25

For understanding the code, first step is mget on the vector of strings

mget(x)

returns a list of data.frame

Then, we are passing this as argument to Map along with the corresponding 'b' vector. ie each element of list is a unit, similarly each element of vector is a unit

Map(function(x, y) x, mget(x), b)

The function(x, y) is anonymous/lambda function construct. Using that we set the names of the second column to that of 'b'. Here, the anonymous argument for 'b' is 'y'. Later, we wrap everything in list2env as it is a named list and it will look up for those names in the global env to update it

It is usually best to work with lists for this type of thing. That can make life easier and is generally a good workflow to learn.

list1 <- list(P1 = P1, P2 = P2, P3 = P3)

# here is your loop
for (i in seq_along(list1)) {
  names(list1[[i]])[2] <- b[i]
}

# you can use Map as well for iteration, similar to @akrun's solution
# this is really identical at this point, except you've created the list differently
Map(function(df, b) {names(df)[2] <- b; df}, list1, b)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM