数据格式化:重新格式化并将r中的多个数据帧重新排列为单个文件

时间:2017-06-09 23:40:34

标签: r list csv dataframe lapply

我有很多.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”将其添加进去。

2 个答案:

答案 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)]