8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

如何制作数据框列表?

Bastien Durel 2月前

137 0

如何制作数据框列表以及如何从列表访问每个数据框?例如,如何将这些数据框放入列表中?d1 <- data.frame(y1 = c(1, 2, 3), ...

如何制作数据框列表以及如何从列表中访问每个数据框?

例如,如何将这些数据框放入列表中?

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))
帖子版权声明 1、本帖标题:如何制作数据框列表?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Bastien Durel在本站《function》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 现在不是了。我刚刚编辑了你的问题以修复代码格式。如果你觉得怀旧,可以随时恢复。

  • 这与您的问题无关,但您想 = 在函数调用中 <- 和 而不是 <- ,您最终会 y1 在您正在工作的任何环境中 y2

    d1 <- data.frame(y1 <- c(1, 2, 3), y2 <- c(4, 5, 6))
    y1
    # [1] 1 2 3
    y2
    # [1] 4 5 6
    

    这不会产生在数据框中创建列名的看似预期的效果:

    d1
    #   y1....c.1..2..3. y2....c.4..5..6.
    # 1                1                4
    # 2                2                5
    # 3                3                6
    

    另一方面,运算符将把你的向量与参数关联 = 起来 data.frame .

    至于您的问题,制作数据框列表很容易:

    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))
    my.list <- list(d1, d2)
    

    你可以像访问任何其他列表元素一样访问数据框:

    my.list[[1]]
    #   y1 y2
    # 1  1  4
    # 2  2  5
    # 3  3  6
    
  • 其他答案向您展示了 已经拥有 一堆数据框 如何 制作数据框列表 d1 , d2 ,... 拥有连续命名的数据框是一个问题,将它们放在列表中是一个很好的解决办法,但最佳做法是避免 首先 在列表中没有一堆数据框

    其他答案提供了大量有关如何将数据框分配给列表元素、访问它们等的详细信息。我们也会在这里稍微介绍一下,但要点不要 don't wait until you have a bunch of a data.frames to add them to a list. Start with the list.

    本回答的其余部分将介绍一些您可能想要创建顺序变量的常见情况,并向您展示如何直接进入列表。如果您是 R 中列表的新手,您可能还想阅读 What's the difference between [[ and [ in accessing elements of a list? .


    从头开始列出清单

    首先, d1 d2 d3 不要创建 dn , ..., d 包含 n 元素的列表。

    将多个文件读入数据框列表

    在目录中 data1.csv, data2.csv, ... 有文件 mydata 。您需要的第一件事是一个包含所有文件名的向量。您可以使用粘贴(例如)来构建它 my_files = paste0("data", 1:5, ".csv") 来获取所有适当的文件 list.files 可能更容易 my_files <- list.files(pattern = "\\.csv$") 。您可以使用正则表达式来匹配文件,如果您需要帮助,请在其他问题中阅读有关正则表达式的更多信息。这样,即使它们不遵循很好的命名方案,您也可以抓取所有 CSV 文件。或者,如果您需要从一堆 CSV 文件中挑选出某些 CSV 文件,您可以使用更花哨的正则表达式模式。

    此时,大多数 R 初学者都会使用循环 for ,这没有什么不妥,它可以很好地工作。

    my_data <- list()
    for (i in seq_along(my_files)) {
        my_data[[i]] <- read.csv(file = my_files[i])
    }
    

    一种更像 R 的方法是使用 lapply ,这是上述的快捷方式

    my_data <- lapply(my_files, read.csv)
    

    当然,可以 read.csv 适当替换其他数据导入功能。 readr::read_csv 或者 data.table::fread 会更快,或者您可能还需要针对不同文件类型使用不同的功能。

    无论哪种方式,将列表元素命名为与文件匹配都很方便

    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 = "")
    

    将数据框拆分为数据框列表

    这非常简单,基本函数 split() 会帮你完成。你可以按数据列(或多列)进行拆分,也可以按你想要的任何其他方式进行拆分

    mt_list = split(mtcars, f = mtcars$cyl)
    # This gives a list of three data frames, one for each value of cyl
    

    这也是将数据框拆分成多个部分以进行交叉验证的好方法。也许你想将其拆分 mtcars 成训练、测试和验证部分。

    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))
    

    但谁只进行一次模拟呢?您想进行 100 次、1000 次甚至更多次!但您希望工作区中有 10,000 个数据帧。使用 replicate 并将它们放在列表中:

    sim_list = replicate(n = 10,
                         expr = {data.frame(x = rnorm(50), y = rnorm(50))},
                         simplify = F)
    

    尤其是在这种情况下,您还应该考虑是否真的需要单独的数据框,或者带有“组”列的单个数据框是否同样有效?使用 data.table dplyr 可以很容易地对数据框进行“按组”操作。

    我没有把我的数据放入列表中:(下次我会这么做,但我现在能做什么?

    如果它们是奇怪的组合(这很不寻常),您可以简单地分配它们:

    mylist <- list()
    mylist[[1]] <- mtcars
    mylist[[2]] <- data.frame(a = rnorm(50), b = runif(50))
    ...
    

    如果你有以某种模式命名的数据框,例如, df1 , df2 , df3 并且你想将它们放在列表中,那么 get 只要你能编写一个正则表达式来匹配名称,就可以实现它们。例如

    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.
    

    通常, mget 用于获取多个对象并以命名列表的形式返回它们。其对应部分 get 用于获取单个对象并返回它(不在列表中)。

    将数据框列表组合成单个数据框

    一个常见的任务是将一串数据框组合成一个大数据框。如果你想将它们堆叠在一起,你可以使用 rbind 一对数据框,但对于一串数据框,这里有三个不错的选择:

    # 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)
    

    (类似地,对列使用 cbind dplyr::bind_cols 。)

    要合并(连接)数据框列表,您可以查看 这些答案 。通常,想法是使用 Reduce with merge (或其他连接函数)将它们组合在一起。

    但我确实需要按顺序命名的变量

    使用它们可能很麻烦,而且几乎总是你不需要它们,但如果你确实需要它们,请尽你所能 list ,然后你可以 list2env() 将所有列表项放入一个环境中,比如你的 .GlobalEnv .

    为什么要将数据放在列表中?

    将相似的数据放在列表中,因为您想对每个数据框执行类似的操作,而像 lapply , sapply do.call , the purrr package 和旧 plyr l*ply 函数这样的函数可以轻松做到这一点。人们使用列表轻松完成操作的例子在 SO 上随处可见。

    即使使用低级的 for 循环,循环遍历列表元素也比用 构造变量名 paste 和用 访问对象 get 。调试也更容易。

    考虑 可扩展性 。如果您实际上只需要三个变量,那么使用就没问题 d1 , d2 , d3 。但是,如果您实际上需要 6 个变量,那么就需要输入更多内容。下次,当您需要 10 或 20 个变量时,您会发现自己正在复制和粘贴代码行,也许使用查找/替换来更改为 d14 d15 并且您会认为 编程不应该是这样的 。如果您使用列表,3 个案例、30 个案例和 300 个案例之间的差异最多是一行代码——如果您的案例数量是通过 .csv 目录中的文件数量自动检测的,则根本没有变化。

    您可以命名列表的元素,以防您想使用数字索引以外的其他东西来访问数据框(并且您可以同时使用两者,这不是 XOR 选择)。

    总的来说,使用列表可以让你编写更干净、更易读的代码,从而减少错误和混乱。

  • 我建议阅读 Stack Overflow 上带有 r 和 list 标签的问题和答案。

  • 我正在执行 dfs <- list.files(pattern = \'^[0-9]\') |> lapply(read.csv),但 dfs 的元素不是数据框而是列表,即 dfs[i] |> class() 给出 > [1] \'list\'。发生了什么事,我如何让 dfs[i] |> class() 给出 > [1] \'dataframe\'?请注意,dfs[i] <- dfs[i] |> as.data.frame() 没有帮助。

  • @Matteo 如果 dfs 是数据框列表,则 dfs[i] 将是一个数据框列表。您需要使用 [[ 来提取单个列表元素,dfs[[i]] 将是一个数据框。请参阅此常见问题解答以了解更多背景信息和解释。

  • 您还可以使用 和 访问每个列表元素中的特定列和值 [ [[ 下面是几个示例。首先,我们可以使用 仅访问列表中每个数据框的第一列 lapply(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, 2)
    # $d1
    # [1] 4
    # 
    # $d2
    # [1] 6
    

    然后,我们还可以直接以向量形式访问列值,使用 [[

    lapply(ldf, "[[", 1)
    # $d1
    # [1] 1 2 3
    #
    # $d2
    # [1] 3 2 1
    
  • 如果您有大量按顺序命名的数据框,则可以创建所需数据框子集的列表,如下所示:

    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.list2 包含第 2、第 3 和第 4 个数据帧的列表。

    [[1]]
      y1 y2
    1  3  6
    2  2  5
    3  1  4
    
    [[2]]
      y1 y2
    1  6  3
    2  5  2
    3  4  1
    
    [[3]]
      y1 y2
    1  9  8
    2  9  8
    3  9  8
    

    但请注意,上述列表中的数据框不再命名。如果您想创建包含数据框子集的列表并希望保留其名称,您可以尝试以下操作:

    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
    

    返回:

    > my.list3
    $d2
      y1 y2
    1  3  6
    2  2  5
    3  1  4
    
    $d3
      y1 y2
    1  6  3
    2  5  2
    3  4  1
    
    $d4
      y1 y2
    1  9  8
    2  9  8
    3  9  8
    
    > str(my.list3)
    List of 3
     $ d2:'data.frame':     3 obs. of  2 variables:
      ..$ y1: num [1:3] 3 2 1
      ..$ y2: num [1:3] 6 5 4
     $ d3:'data.frame':     3 obs. of  2 variables:
      ..$ y1: num [1:3] 6 5 4
      ..$ y2: num [1:3] 3 2 1
     $ d4:'data.frame':     3 obs. of  2 variables:
      ..$ y1: num [1:3] 9 9 9
      ..$ y2: num [1:3] 8 8 8
    
    > my.list3[[1]]
      y1 y2
    1  3  6
    2  2  5
    3  1  4
    
    > my.list3$d4
      y1 y2
    1  9  8
    2  9  8
    3  9  8
    
  • 引用 10

    假设您有大量具有相似名称的数据框(此处为 d#,其中 # 是某个正整数),以下是 @mark-miller 方法的轻微改进。它更简洁,并返回一个 命名 的数据框列表,其中列表中的每个名称都是相应的原始数据框的名称。

    关键是 mget 与一起 ls 。如果问题中提供的数据框 d1 和 d2 是环境中唯一名为 d# 的对象,那么

    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
    

    此方法利用了 中的模式参数 ls ,它允许我们使用正则表达式对环境中的对象名称进行更精细的解析。正则表达式的替代方法 "^d[0-9]+$" "^d\\d+$" .

    正如 @gregor 指出的 那样,总体而言,设置数据构建过程以便将数据框在开始时放入命名列表中是一种更好的做法。

    数据

    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 <- 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))
    
    my.list <- list(d1, d2)
    

    然后,如果你想要访问其中一个数据框中的特定值,你可以按顺序使用双括号来实现。第一组带你进入数据框,第二组带你到特定坐标:

    my.list[[1]][3, 2]
    
    [1] 6
    
  • for 循环模拟

    如果我有一个 for 循环生成数据框,我会从一个空开始 list() ,并在生成数据框时附加它们。

    # Empty list
    dat_list <- list()
    
    for(i in 1:5){
        # Generate dataframe
        dat <- data.frame(x=rnorm(10), y=rnorm(10))
        # Add to list
        dat_list <- append(dat_list, list(dat))
    }
    

    请注意,它 list(dat) 在我们的 append() 调用中。

    访问数据

    我们使用从列表中 n 获取 dat_list[[n]] 。您可以以正常方式访问此数据框内的数据,例如 dat_list[[2]]$x .

    或者如果你想要从所有数据框中获取相同的部分 sapply(dat_list, "[", "x") .

    请参阅 @Gregor Thomas 的答案,了解如何在不使用 for 循环的情况下执行此操作。

  • 这可能有点晚了,但回到你的例子,我想我会稍微扩展一下答案。

     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))
    

    然后你可以轻松地列出清单:

    mylist <- list(D1,D2,D3,D4)
    

    现在你有了一个列表,但不能像以前那样访问列表,例如

    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)
    

    希望这点额外的帮助。

    干杯!

  • 是的,我知道,但是出于某种原因,当我复制和粘贴时,所有内容都变成了大写。:( 无论如何,小写代码都可以工作。

  • 我很好奇为什么您更喜欢 GETDF_FROMLIST(mylist, 1) 而不是 mylist[[1]]?如果您更喜欢函数语法,您甚至可以执行 \'[[\'(mylist, 1) 而无需定义自定义函数。

  • 引用 16

    您还可以简化函数定义,函数的整个主体可以只是 return(DF_LIST[[ITEM_LOC]]),无需分配中间变量。

  • Rook 2月前 0 只看Ta
    引用 17

    非常简单!以下是我的建议:

    如果您想在工作区中选择数据框,请尝试以下操作:

    Filter(function(x) is.data.frame(get(x)) , ls())
    

    或者

    ls()[sapply(ls(), function(x) is.data.frame(get(x)))]
    

    所有这些都将产生相同的结果。

    您可以更改 is.data.frame 以检查其他类型的变量,例如 is.function

  • 在tidyverse中,您可以使用该功能 lst() 根据对象自动命名列表。

    library(tibble)
    
    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))
    
    lst(d1, d2)
    # $d1
    # y1 y2
    # 1  1  4
    # 2  2  5
    # 3  3  6
    # 
    # $d2
    # y1 y2
    # 1  3  6
    # 2  2  5
    # 3  1  4
    

    当您编译稍后想要按名称引用的列表时,这会很有帮助。

返回
作者最近主题: