【问题标题】:Can you store names of tibbles into a list to access later?您可以将小标题的名称存储到列表中以供以后访问吗?
【发布时间】:2020-10-03 16:17:26
【问题描述】:

我希望将一些小标题的名称存储到一个列表中,稍后我将使用该列表分别遍历每个小标题。有没有办法做到这一点?

##This is how I am reading in my data from a csv's
i <- 1
for (name in datasets) {
  file <- paste(".csv", name, sep="")
  
  assign(paste0("DF", i), read_csv(file))
  
  i <- i + 1
  list_of_df <- c(list_of_df, )
}

list <- c(tib1, tib2 tib3)
  for(tibble in list) {
    #do things here
  }

【问题讨论】:

  • 什么是list_of_df?注:(1)tibble::lst默认使用对象名; (2) 使用lapply 更有效地构建框架列表,请参阅stackoverflow.com/a/24376207/3358272; (3) 命名列表list 是非常糟糕的做法,不清楚(人眼)您是指基本R 函数list 还是您创建的名为list 的变量; (4) 虽然lapply 通常更好,但在for 循环中使用for (nm in names(list_of_frames)) { dat &lt;- list_of_frames[[nm]]; ... } 可能更有用,这样您就可以在循环体中同时拥有数据及其名称。
  • 我认为您使用的文件有误paste(".csv", name, sep="") => .csvname。还有为什么不使用paste0。你也将它们命名为DF# 并使用tib#

标签: r data-science


【解决方案1】:

根据我的评论:

files <- paste0(datasets, ".csv")
list_of_df  <- lapply(1:length(files), function(x){
     assign(y<-paste0("tib", x), read_csv(files[x]), envir=.GlobalEnv)
     y
})
### Another way to it / Simpler:
list_of_df  <- lapply(files, read_csv)
names(list_of_df) <- paste0("tib", 1:length(files))
list2env(list_of_df)

names <- paste0("tib", 1:3)
lapply(names, function(x){
    get(x,  envir=.GlobalEnv)
})
# Or
for(x in names){
   tib <- get(x)
}

【讨论】:

  • fortunes::fortune(236)唯一应该使用 assign 功能的人是那些完全理解为什么永远不应该使用 assign 功能的人。 -- Greg Snow R-help(2009 年 7 月)
【解决方案2】:

如果我理解正确,OP 在环境中创建单独的小标题,但希望将小标题的名称存储在列表中,以便分别遍历每个小标题。

通常的做法是将 数据对象 存储在列表中,而不是将小标题的 名称 存储在列表中:

library(dplyr)
datasets <- c("Dataset_A", "Dataset_B")
file_names <- paste0(datasets, ".csv")
list_of_tibbles <- lapply(file_names, readr::read_csv) %>% 
  setNames(datasets)

对于给定的示例文件(见下文),我们得到

list_of_tibbles
$Dataset_A
# A tibble: 2 x 2
     ID   val
  <dbl> <dbl>
1     1 0.288
2     2 0.788

$Dataset_B
# A tibble: 2 x 2
     ID   val
  <dbl> <dbl>
1     1 0.409
2     2 0.883

现在,我们可以按照 OP 的要求遍历小标题列表

for (tib in list_of_tibbles) {
  # do things here
    print(sum(tib$val))
}
[1] 1.075883
[1] 1.291994

在许多情况下,lapply() 更方便,因为它再次将操作结果作为列表返回:

lapply(list_of_tibbles, function(x) sum(x$val))
$Dataset_A
[1] 1.075883

$Dataset_B
[1] 1.291994

我的首选方法是将单个小标题组合成一个大标题,然后使用分组来对单个小标题的数据进行操作

combined_tibble <- lapply(file_names, readr::read_csv) %>% 
  setNames(datasets) %>% 
  bind_rows(.id = "source")

combined_tibble
  source       ID   val
  <chr>     <dbl> <dbl>
1 Dataset_A     1 0.288
2 Dataset_A     2 0.788
3 Dataset_B     1 0.409
4 Dataset_B     2 0.883

source 列表示每一行的来源,可用于按组聚合,例如,

combined_tibble %>% 
  group_by(source) %>% 
  summarize(sum(val))
  source    `sum(val)`
  <chr>          <dbl>
1 Dataset_A       1.08
2 Dataset_B       1.29

为了完整起见,这里是使用data.table的相同方法:

library(data.table)
datasets <- c("Dataset_A", "Dataset_B")
file_names <- paste0(datasets, ".csv")
combined_dt <- lapply(file_names, fread) %>% 
  setNames(datasets) %>% 
  rbindlist(idcol = "source")

combined_dt
      source ID       val
1: Dataset_A  1 0.2875775
2: Dataset_A  2 0.7883051
3: Dataset_B  1 0.4089769
4: Dataset_B  2 0.8830174
combined_dt[, sum(val), by = source]
      source       V1
1: Dataset_A 1.075883
2: Dataset_B 1.291994

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-21
    • 2021-10-11
    • 2020-10-02
    • 2010-12-04
    • 1970-01-01
    • 2011-07-12
    • 1970-01-01
    • 2016-03-18
    相关资源
    最近更新 更多