bill999
bill999

Reputation: 2540

Change column names of many data frames in a for-loop

I have a bunch of data frames generated by:

for(i in 1:100){
    assign(paste("df", i, sep=""), data.frame(1,2))
}

I want to rename the first column of all of these 100 data frames to be Column1. (Note that in my real data each first column is unique, unlike the example here, where they are each X1.) This will be the same for all data frames.

For any individual one, I can do this. For example:

names(df45)[1]<-"Column1"

However, I am running into problems when attempting to automate the process. Here is the (wrong) code I have tried:

names(eval(parse(text=paste("df", i, sep=""))))[1] <- "Column1"

How should I modify this? And is there a quicker way to access variables in loops that this?

I have come across other answers that say it is better to put these things in a list and process it like this:

#put into a list
l.df <- lapply(ls(pattern="df[0-9]+"), function(x) get(x))

for(i in 1:100){
    names(l.df[[i]])[1] <- "Column1"
}

However, I want to be able to merge all the data frames together as follows:

df <- merge(df1, df2, df3, df4, ....... df100, by="Column1")

Upvotes: 2

Views: 3896

Answers (2)

Roman Luštrik
Roman Luštrik

Reputation: 70653

First of all, I would work on a list (of data.frames). You can use lapply to "climb" each list element. I'm borrowing the merge approach from @baptiste (posted in comments).

xy <- replicate(10, data.frame(a = 1:10, b = runif(10)), simplify = FALSE)
xy <- lapply(xy, function(x) {names(x)[1] <- "Golum1"; x})
Reduce(function(x,y) merge(x,y,by="Golum1"), xy)

   Golum1          b.x        b.y        b.x        b.y       b.x        b.y       b.x       b.y        b.x        b.y
1       1 0.0002497286 0.44790338 0.12656118 0.85306085 0.9502253 0.92816557 0.6727456 0.3615492 0.71520420 0.26933313
2       2 0.1416911036 0.56330792 0.03834924 0.95777112 0.4763716 0.28533075 0.8729803 0.7035205 0.49824660 0.15685903
3       3 0.3454216446 0.42778131 0.35065726 0.35513107 0.6610847 0.21600874 0.9611296 0.2527102 0.62142047 0.32401890
4       4 0.2128049061 0.20300980 0.35529195 0.19681124 0.6105881 0.85292309 0.3311055 0.4953804 0.05079081 0.98322541
5       5 0.5967234119 0.93926727 0.74456886 0.25971581 0.3739592 0.01498909 0.2683361 0.9895955 0.45829244 0.76854781
6       6 0.4843087369 0.04535037 0.29100912 0.05801034 0.1010084 0.31980135 0.7572697 0.6022717 0.86408382 0.10516840
7       7 0.0624480459 0.58510411 0.62256365 0.97236759 0.6910560 0.21823825 0.8169870 0.3162987 0.79414611 0.43907780
8       8 0.1764713391 0.05768646 0.30316764 0.25180931 0.9378119 0.06416274 0.6814944 0.9889381 0.13944101 0.51939788
9       9 0.9533833019 0.70950657 0.04435285 0.92314396 0.4208451 0.34137729 0.8876309 0.9789025 0.43711122 0.71978702
10     10 0.7814107563 0.93566272 0.76036172 0.71139862 0.5308587 0.19734855 0.8359664 0.6903358 0.22433803 0.09343658

# warnings are due to name collisions

Upvotes: 4

Mario Fajardo
Mario Fajardo

Reputation: 640

Maybe this works for you

 for(i in 1:100){
  assign(paste("df", i, sep=""), data.frame(1,2))
}

require(naturalsort)
data<-do.call(rbind,sapply(ls(pattern="df[0-9]+"),function(x) get(x),simplify = F))
data<-data[naturalorder(rownames(data)),]

colnames(data)[1] <-'Column1'

head(data)

Upvotes: 1

Related Questions