11

I have a series of data frames, df1 df2, where each data frame follow this structure:

x <- c(1:5)
y <- c(1:5)
df1 <- data.frame("Row One"=x, "Row Two"=y)

Sample output for df1:

 Row.One    Row.Two
    1           1
    2           2
    3           3
    4           4
    5           5

I put each data frame into a list dfList <- list(df1,df2...)

Now I want to loop through each data frame object in this list to replace the column names using this command:

a <- grep("One", colnames(df))
b <- grep("Two", colnames(df))

names(df)[a] <- "R1"
names(df)[b] <- "R2"

How can I structure a loop in R so that I no matter how many data frames are in the list object the column name changing commands above will be applied to each data frame?

AME
  • 5,234
  • 23
  • 71
  • 81

3 Answers3

20
> df1 <- data.frame("Row One"=x, "Row Two"=y)
> df2 <- data.frame("Row Two"=y,"Row One"=x)
> dfList <- list(df1,df2)
> lapply(dfList, function(x) {
                    names(x)[ grep("One", names(x))] <- "R1"
                    names(x)[ grep("Two", names(x))] <- "R2"
                    x} )
[[1]]
  R1 R2
1  1  1
2  2  2
3  3  3
4  4  4
5  5  5

[[2]]
  R2 R1
1  1  1
2  2  2
3  3  3
4  4  4
5  5  5
IRTFM
  • 258,963
  • 21
  • 364
  • 487
  • This works well but when I call `dflist[[1]]` it still shows "Row One" instead of "R1". Why does the change only appear on the console when I run the `lapply` command but does not update the data frame itself? Am I doing something wrong? – AME Oct 19 '13 at 04:58
  • 1
    If you don't assgn the result to a named object it "disappears". If you want it to replace dfList you need to use `dfList <- `. – IRTFM Oct 19 '13 at 05:12
5

Just use length(dfList)?

for(i in 1:length(dfList))
{
    a <- grep("One", names(dfList[[i]]))
    ... #etc.
}

Using lapply will be faster.

ChangeNames = function(Data)
{
    a = grep("One", names(Data))
    b = grep("Two", names(Data))
    names(Data)[c(a,b)] <- c("R1", "R2")
    return(Data)
}
lapply(dfList, ChangeNames) #Returns list of renamed data frames.
Señor O
  • 17,049
  • 2
  • 45
  • 47
  • Does this also work if "a" is empty? It seems like it would assign "R1" to "b". – Frank Oct 18 '13 at 22:59
  • No it doesn't. OP just wants that command applied to every data frame in the list. – Señor O Oct 18 '13 at 23:01
  • Okay. I'm used to seeing grep as a conditional thing ("If I find expr..."), but, yeah, the OP seems to know there will be one match for each. – Frank Oct 18 '13 at 23:03
  • Yeah if there's no match, `grep` will return `integer(0)`, so that `c(a,b)` would be the same as `b` if `a` found no match. – Señor O Oct 18 '13 at 23:04
4

Or use llply (from plyr) or lapply like so:

library(plyr)
result_list <- llply(list_of_df, function(x) {
                # do the replacing
                return(x)
                })
Maiasaura
  • 32,226
  • 27
  • 104
  • 108