56

我有一个文件列表。我还有一个“名称”列表,我substr()来自这些文件的实际文件名。我想为列表中的每个文件添加一个新列。此列将包含“名称”中的相应元素,重复次数为文件中的行数。

例如:

df1 <- data.frame(x = 1:3, y=letters[1:3])
df2 <- data.frame(x = 4:6, y=letters[4:6])
filelist <- list(df1,df2)
ID <- c("1A","IB")

伪代码

  for( i in length(filelist)){

       filelist[i]$SampleID <- rep(ID[i],nrow(filelist[i])

  }

// 基本上在filelist中的每个数据帧中创建一个新列,并用重复的ID对应值填充该列

我的输出应该是这样的:

filelist[1]应该:

   x y SAmpleID
 1 1 a       1A
 2 2 b       1A
 3 3 c       1A

fileList[2]

   x y SampleID
 1 4 d       IB
 2 5 e       IB
 3 6 f       IB

等等.....

任何想法如何完成。

4

6 回答 6

65

另一种解决方案是使用 cbind,并利用 R 将循环使用较短向量的值这一事实。

例如

x <- df2  # from above
cbind(x, NewColumn="Singleton")
 #    x y NewColumn
 #  1 4 d Singleton
 #  2 5 e Singleton
 #  3 6 f Singleton

没有必要使用rep. R 为您做到这一点。

因此,您可以放入 cbind(filelist[[i]], ID[[i]])您的for loopor 正如@Sven 指出的那样,您可以使用清洁器mapply

filelist <- mapply(cbind, filelist, "SampleID"=ID, SIMPLIFY=F)
于 2012-11-15T22:30:29.327 回答
24

这是您的循环的更正版本:

for( i in seq_along(filelist)){

  filelist[[i]]$SampleID <- rep(ID[i],nrow(filelist[[i]]))

}

有3个问题:

  • 一个决赛)在身体命令后丢失。
  • 列表的元素由 访问[[,而不是由访问[[返回长度为 1 的列表。[[仅返回元素。
  • length(filelist)只是一个值,因此循环仅针对列表的最后一个元素运行。我用seq_along(filelist).

更有效的方法是mapply用于任务:

mapply(function(x, y) "[<-"(x, "SampleID", value = y) ,
       filelist, ID, SIMPLIFY = FALSE)
于 2012-11-15T19:51:53.180 回答
7

purrr方式,使用map2

library(dplyr)
library(purrr)

map2(filelist, ID, ~cbind(.x, SampleID = .y))

#[[1]]
#  x y SampleId
#1 1 a       1A
#2 2 b       1A
#3 3 c       1A

#[[2]]
#  x y SampleId
#1 4 d       IB
#2 5 e       IB
#3 6 f       IB

或者也可以使用

map2(filelist, ID, ~.x %>% mutate(SampleId = .y))

如果您命名列表,我们可以imap根据其名称使用和添加新列。

names(filelist) <- c("1A","IB")
imap(filelist, ~cbind(.x, SampleID = .y))
#OR
#imap(filelist, ~.x %>% mutate(SampleId = .y))

这类似于使用Map

Map(cbind, filelist, SampleID = names(filelist))
于 2020-02-14T00:52:49.293 回答
6

这个对我有用:

为列表中的每个数据框创建一个新列;根据现有列填充新列的值。(在您的情况下,ID)。

例子:

# Create dummy data
df1<-data.frame(a = c(1,2,3))
df2<-data.frame(a = c(5,6,7))

# Create a list
l<-list(df1, df2)

> l
[[1]]
  a
1 1
2 2
3 3

[[2]]
  a
1 5
2 6
3 7

# add new column 'b'
# create 'b' values based on column 'a' 
l2<-lapply(l, function(x) 
  cbind(x, b = x$a*4))

结果是:

> l2
[[1]]
  a  b
1 1  4
2 2  8
3 3 12

[[2]]
  a  b
1 5 20
2 6 24
3 7 28

在您的情况下,例如:

filelist<-lapply(filelist, function(x) 
  cbind(x, b = x$SampleID))
于 2018-05-22T17:46:29.037 回答
3

一个棘手的方法:

library(plyr)

names(filelist) <- ID
result <- ldply(filelist, data.frame)
于 2017-04-02T20:59:26.903 回答
1
data_lst <- list(
  data_1 = data.frame(c1 = 1:3, c2 = 3:1),
  data_2 = data.frame(c1 = 1:3, c2 = 3:1)
)

f <- function (data, name){
  data$name <- name
  data
}

Map(f, data_lst , names(data_lst)) 
于 2020-04-11T10:52:31.940 回答