我有很多.csv文件是来自其他来源的自动格式化数据。对于我(任何人的!)分析,该数据的顺序非常糟糕。理想情况下,我希望将所有这些单独的.csv文件合并到一个数据框中,其中每一行代表原始数据框的内容,并且该行中的第一列具有原始数据框的名称。
我可以使用列表
自动导入每个原始数据帧#import from working directory
temp = list.files(pattern="*.csv")
list2env(
lapply(setNames(temp, make.names(gsub("*.csv$", "", temp))),
read.csv), envir = .GlobalEnv)
#make a new list of dataframes that I should be able to use with "lapply"
files<-eapply(.GlobalEnv,is.data.frame)
我想以下列方式重新格式化列表中的每个数据帧:
#reproducible example original format
df1<-data.frame(matrix(NA, nrow=3, ncol=3))
colnames(df1)<-c("area", "mean", "sd")
rownames(df1)<-c("A", "B", "C")
df1[1:3,1]<-30
df1[,2]<-sample(80:100, 3, replace=TRUE)
df1[,3]<-sample(1:5, 3, replace=TRUE)
df1
area mean sd
A 30 81 1
B 30 96 3
C 30 97 4
df2<-data.frame(matrix(NA, nrow=3, ncol=3))
colnames(df2)<-c("area", "mean", "sd")
rownames(df2)<-c("A", "B", "C")
df2[1:3,1]<-35
df2[,2]<-sample(80:100, 3, replace=TRUE)
df2[,3]<-sample(1:5, 3, replace=TRUE)
df2
area mean sd
A 35 82 2
B 35 99 1
C 35 100 3
#desired final format:
filename area.1 mean.1a sd.1a mean.1b sd.1b mean.1c sd.1c
1 file1 30 81 1 96 3 97 4
2 file2 35 82 2 99 1 100 3
我一直试图写一个基本上这样做的丑陋循环:
#desired final format
df1.2<-data.frame(matrix(NA, nrow=2, ncol=8))
colnames(df1.2)<-c("filename", "area.1", "mean.1a", "sd.1a", "mean.1b", "sd.1b", "mean.1c", "sd.1c")
df1.2[1,1]<-"file1"
df1.2[1,2]<-df1[1,1]
df1.2[1,3]<-df1[1,2]
df1.2[1,4]<-df1[1,3]
df1.2[1,5]<-df1[2,2]
df1.2[1,6]<-df1[2,3]
df1.2[1,7]<-df1[3,2]
df1.2[1,8]<-df1[3,3]
但我无法弄清楚如何从列表中操纵数据框中的个别元素。
我知道必须有一种有效的方法来做到这一点,但我以前从未真正使用过列表,我无法弄清楚如何让它按照我想要的方式运行。我发现的所有示例似乎都在使用lapply来执行更基本的操作,例如平均整行或更改整个属性,而不是复制列表中数据框内的单个元素。
我对列表不太熟悉,我认为这让我心疼。我会喜欢使用lapply和/或for循环(或者我不知道的一些神奇函数)的帮助,这样我就可以编写一个脚本来迭代列表中的所有数据帧,并同时包含文件名作为第一列,或者稍后使用“rbind”将其添加进去。
答案 0 :(得分:0)
我是否理解您的输入数据是数据帧列表?
如果是这样的话,这里有一大堆胶带可以带你去那里。
biglist <- list()
areas <- seq(30,45,by=5)
for(i in 1:4) {
biglist[[i]]<-data.frame(matrix(NA, nrow=3, ncol=3))
colnames(biglist[[i]])<-c("area", "mean", "sd")
rownames(biglist[[i]])<-c("A", "B", "C")
biglist[[i]][1:3,1]<-areas[i]
biglist[[i]][,2]<-sample(80:100, 3, replace=TRUE)
biglist[[i]][,3]<-sample(1:5, 3, replace=TRUE)
}
biglist
## [[1]]
## area mean sd
## A 30 100 3
## B 30 86 1
## C 30 85 1
##
## [[2]]
## area mean sd
## A 35 83 4
## B 35 87 2
## C 35 88 4
##
## [[3]]
## area mean sd
## A 40 92 4
## B 40 80 3
## C 40 90 5
##
## [[4]]
## area mean sd
## A 45 97 2
## B 45 92 3
## C 45 92 5
现在有趣的部分......
df1.2<-data.frame(matrix(NA, nrow=length(biglist), ncol=8))
colnames(df1.2)<-c("filename", "area.1", "mean.1a", "sd.1a", "mean.1b", "sd.1b", "mean.1c", "sd.1c")
for(i in 1:length(biglist)) {
df1.2[i,2:8] <- c(biglist[[i]][1,], biglist[[i]][2,2:3], biglist[[i]][3,2:3])
}
df1.2$filename <- paste0("file",1:length(biglist))
df1.2
## filename area.1 mean.1a sd.1a mean.1b sd.1b mean.1c sd.1c
## 1 file1 30 100 3 86 1 85 1
## 2 file2 35 83 4 87 2 88 4
## 3 file3 40 92 4 80 3 90 5
## 4 file4 45 97 2 92 3 92 5
不是最优雅的,但这会得到你所需要的吗?
答案 1 :(得分:0)
如果每个数据框具有相同的行数,则可以使用ord()
将它们展平,然后将它们绑定在公共数据框中。例如:
unlist
输出:
df1 <- unlist(df1)
df2 <- unlist(df2)
df <- data.frame()
df <- rbind(df, c("file1", df1), stringsAsFactors = F)
df <- rbind(df, c("file2", df2), stringsAsFactors = F)
colnames(df) <- c("filname", names(df1))
df <- df[,-c(3:4)]