R 如何制作数据帧列表?
如何制作数据帧列表以及如何从列表中访问这些数据帧 例如,如何将这些数据帧放入列表中R 如何制作数据帧列表?,r,list,dataframe,r-faq,R,List,Dataframe,R Faq,如何制作数据帧列表以及如何从列表中访问这些数据帧 例如,如何将这些数据帧放入列表中 d1 <- data.frame(y1 = c(1, 2, 3), y2 = c(4, 5, 6)) d2 <- data.frame(y1 = c(3, 2, 1), y2 = c(6, 5, 4)) d1这与您的问题无关,但您希望使用=而不是如果您有大量按顺序命名的数据帧,您可以创建所需数据帧子集的列表,如下所示: d1 <
d1 <- data.frame(y1 = c(1, 2, 3),
y2 = c(4, 5, 6))
d2 <- data.frame(y1 = c(3, 2, 1),
y2 = c(6, 5, 4))
d1这与您的问题无关,但您希望使用=
而不是如果您有大量按顺序命名的数据帧,您可以创建所需数据帧子集的列表,如下所示:
d1 <- data.frame(y1=c(1,2,3), y2=c(4,5,6))
d2 <- data.frame(y1=c(3,2,1), y2=c(6,5,4))
d3 <- data.frame(y1=c(6,5,4), y2=c(3,2,1))
d4 <- data.frame(y1=c(9,9,9), y2=c(8,8,8))
my.list <- list(d1, d2, d3, d4)
my.list
my.list2 <- lapply(paste('d', seq(2,4,1), sep=''), get)
my.list2
my_sim_data = data.frame(x = rnorm(50), y = rnorm(50))
但是,请注意,上面列表中的数据帧不再命名。如果要创建包含数据帧子集的列表并希望保留其名称,可以尝试以下操作:
list.function <- function() {
d1 <- data.frame(y1=c(1,2,3), y2=c(4,5,6))
d2 <- data.frame(y1=c(3,2,1), y2=c(6,5,4))
d3 <- data.frame(y1=c(6,5,4), y2=c(3,2,1))
d4 <- data.frame(y1=c(9,9,9), y2=c(8,8,8))
sapply(paste('d', seq(2,4,1), sep=''), get, environment(), simplify = FALSE)
}
my.list3 <- list.function()
my.list3
这可能有点晚了,但是回到你的例子,我想我会稍微扩展一下答案
D1 <- data.frame(Y1=c(1,2,3), Y2=c(4,5,6))
D2 <- data.frame(Y1=c(3,2,1), Y2=c(6,5,4))
D3 <- data.frame(Y1=c(6,5,4), Y2=c(3,2,1))
D4 <- data.frame(Y1=c(9,9,9), Y2=c(8,8,8))
您可以使用此函数获取和分配所选的数据帧
GETDF_FROMLIST <- function(DF_LIST, ITEM_LOC){
DF_SELECTED <- DF_LIST[[ITEM_LOC]]
return(DF_SELECTED)
}
GETDF\u FROMLIST您还可以使用[
和[[
访问每个列表元素中的特定列和值。这里有几个示例。首先,我们可以使用lappy(ldf,“[”,1)
访问列表中每个数据帧的第一列,其中1
表示列号
ldf <- list(d1 = d1, d2 = d2) ## create a named list of your data frames
lapply(ldf, "[", 1)
# $d1
# y1
# 1 1
# 2 2
# 3 3
#
# $d2
# y1
# 1 3
# 2 2
# 3 1
然后,我们还可以使用[
lapply(ldf, "[[", 1)
# $d1
# [1] 1 2 3
#
# $d2
# [1] 3 2 1
其他答案向您展示了如何在已经有一堆数据帧的情况下创建数据帧列表,例如,d1
,d2
,…按顺序命名数据帧是一个问题,将它们放入列表是一个很好的解决方法,但最佳做法是避免在fi中有一堆不在列表中的数据帧第一名
其他答案提供了大量关于如何将数据帧分配给列表元素、访问这些元素等的详细信息。我们在这里也会介绍一点,但要点是不要等到有一堆数据。帧才能将它们添加到列表中。从列表开始
这个答案的其余部分将介绍一些常见的情况,在这些情况下,您可能会试图创建顺序变量,并向您展示如何直接进入列表
从一开始就列出
首先不要创建d1
d2
d3
,…,dn
。创建一个包含n
元素的列表d
将多个文件读入数据帧列表
这在读取文件时非常容易。也许你的目录中有文件data1.csv,data2.csv,
。你的目标是一个名为mydata
的数据帧列表。你需要的第一件事是一个包含所有文件名的向量。你可以用粘贴(例如,myu files=paste0(“data”,1:5,.csv”)
)来构建它,但使用list.files
获取所有适当的文件可能更容易:my_files假设您拥有“大量”具有类似名称的数据帧(这里d#其中#是某个正整数),下面是对@mark miller方法的一点改进。它更简洁,返回一个命名的data.frames列表,其中列表中的每个名称都是对应的原始data.frames的名称
关键是将mget
与ls
一起使用。如果问题中提供的数据帧d1和d2是环境中唯一名为d#的对象,则
my.list <- mget(ls(pattern="^d[0-9]+"))
此方法利用了ls
中的模式参数,它允许我们使用正则表达式对环境中的对象名称进行更精细的解析。regex“^d[0-9]+$”
的另一个替代方法是“^d\\d+$”
作为@gregor,设置数据构造过程是一个更好的整体,这样data.frames在开始时就被放入命名列表中
数据
d1 <- data.frame(y1 = c(1,2,3),y2 = c(4,5,6))
d2 <- data.frame(y1 = c(3,2,1),y2 = c(6,5,4))
d1非常简单!以下是我的建议:
如果要在工作区中选择数据帧,请尝试以下操作:
Filter(function(x) is.data.frame(get(x)) , ls())
或
所有这些都将给出相同的结果
可以更改<代码>是.DATA。框架< /代码>检查其他类型的变量,如<代码>是。函数< /COD> < /P> < P> >我认为自己是一个完整的新手,但我认为我对这里没有说明的原始子问题有一个非常简单的答案:访问数据帧或部分。
让我们从创建包含数据帧的列表开始,如上所述:
d1是的,我知道,但由于某种原因,当我复制和粘贴时,所有内容都变成了大写。:(无论如何,小写的代码是有效的。我很好奇为什么你更喜欢GETDF_FROMLIST(mylist,1)
而不是mylist[[1]]
?如果你喜欢函数语法,你甚至可以做”[[(mylist,1)
无需定义自定义函数。您还可以简化函数定义,函数的整个主体可以是返回(DF_LIST[[ITEM_LOC]])
,无需指定中间变量。这是几个答案中的一个,但也值得在这里有一个可见的注释:使用=
而不是看看那些没有空格的乱七八糟的代码,不再是了。我刚刚编辑了你的问题以修复代码格式。如果你觉得怀旧,请随时回复。你推荐哪本书这包括使用列表?我建议阅读关于堆栈溢出的问题和答案,这些问题和答案都带有r
和list
@Gregor标记。我想补充一点,我们可以通过简单地分配my_数据来避免命名列表元素以匹配文件,这是可能的,但是my_数据我同意你所说的,但正如我所说,这样做可以避免命名文件的阶段。names(my_data)而不是lappy(foo,get)
,只需使用mget(foo)
mylist[[1]] # to access 'd1'
GETDF_FROMLIST <- function(DF_LIST, ITEM_LOC){
DF_SELECTED <- DF_LIST[[ITEM_LOC]]
return(DF_SELECTED)
}
D1 <- GETDF_FROMLIST(mylist, 1)
D2 <- GETDF_FROMLIST(mylist, 2)
D3 <- GETDF_FROMLIST(mylist, 3)
D4 <- GETDF_FROMLIST(mylist, 4)
ldf <- list(d1 = d1, d2 = d2) ## create a named list of your data frames
lapply(ldf, "[", 1)
# $d1
# y1
# 1 1
# 2 2
# 3 3
#
# $d2
# y1
# 1 3
# 2 2
# 3 1
lapply(ldf, "[", 1, 2)
# $d1
# [1] 4
#
# $d2
# [1] 6
lapply(ldf, "[[", 1)
# $d1
# [1] 1 2 3
#
# $d2
# [1] 3 2 1
my_data <- list()
for (i in seq_along(my_files)) {
my_data[[i]] <- read.csv(file = my_files[i])
}
my_data <- lapply(my_files, read.csv)
names(my_data) <- gsub("\\.csv$", "", my_files)
# or, if you prefer the consistent syntax of stringr
names(my_data) <- stringr::str_replace(my_files, pattern = ".csv", replacement = "")
mt_list = split(mtcars, f = mtcars$cyl)
# This gives a list of three data frames, one for each value of cyl
groups = sample(c("train", "test", "validate"),
size = nrow(mtcars), replace = TRUE)
mt_split = split(mtcars, f = groups)
# and mt_split has appropriate names already!
my_sim_data = data.frame(x = rnorm(50), y = rnorm(50))
sim_list = replicate(n = 10,
expr = {data.frame(x = rnorm(50), y = rnorm(50))},
simplify = F)
mylist <- list()
mylist[[1]] <- mtcars
mylist[[2]] <- data.frame(a = rnorm(50), b = runif(50))
...
df_list = mget(ls(pattern = "df[0-9]"))
# this would match any object with "df" followed by a digit in its name
# you can test what objects will be got by just running the
ls(pattern = "df[0-9]")
# part and adjusting the pattern until it gets the right objects.
# base option - slower but not extra dependencies
big_data = do.call(what = rbind, args = df_list)
# data table and dplyr have nice functions for this that
# - are much faster
# - add id columns to identify the source
# - fill in missing values if some data frames have more columns than others
# see their help pages for details
big_data = data.table::rbindlist(df_list)
big_data = dplyr::bind_rows(df_list)
my.list <- mget(ls(pattern="^d[0-9]+"))
my.list
$d1
y1 y2
1 1 4
2 2 5
3 3 6
$d2
y1 y2
1 3 6
2 2 5
3 1 4
d1 <- data.frame(y1 = c(1,2,3),y2 = c(4,5,6))
d2 <- data.frame(y1 = c(3,2,1),y2 = c(6,5,4))
Filter(function(x) is.data.frame(get(x)) , ls())
ls()[sapply(ls(), function(x) is.data.frame(get(x)))]