【问题标题】:Merge iteratively one of multiple columns to dataframes in a list将多个列中的一个迭代合并到列表中的数据框
【发布时间】:2019-12-16 05:19:07
【问题描述】:

在将单个数据框中的列与列表中的其他数据框迭代组合时,我遇到了一个(可能很小)问题。一些数据来说明:

# load example data
library(vegan)
data(varechem)
data(varespec)

# generate predictor tables with overlapping rows and different amount of cols
varespec1 <- varespec[c(1:9), ]
varespec2 <- varespec[c(8:16), c(1:43)]
varespec3 <- varespec[c(14:24), c(1:41)]

# store predictor tables in list
subset_list <- list(varespec1 = varespec1, 
  varespec2 = varespec2, 
  varespec3 = varespec3)

# generate a table that holds ALL possible response variables as presence/absence
varechem_binary <- as.data.frame(apply(varechem, 2, cut, 
  breaks = c(-Inf, 1.0, Inf), labels = c("Absent", "Present")))
row.names(varechem_binary) <- row.names(varechem)

上面的代码说明了我是如何为分类任务准备数据的。现在的想法是,列表中包含预测变量 (varespec1, ...) 的 data.frames 应该用于预测响应表 (varechem_binary) 中的每一列,但只有一个一次。很容易将响应表与每个预测器表合并:

# merge response table with each predictor table
merge_counter <- 0
merged_list <- list()
for(table in subset_list) {
    merge_counter <- merge_counter + 1
    current_name <- names(subset_list)[merge_counter]
    tmp <- merge(table, varechem_binary, by = "row.names")
    row.names(tmp) <- tmp$Row.names
    tmp <- tmp[, -1]
    merged_list[[current_name]] <- tmp
    rm(tmp)
}

预期输出:

我现在(或在代码中更早的部分,如果这更有意义的话)正在寻找的是一种将每个预测变量表与响应表 varechem 中的每一列且恰好其中一个列组合在一起的方法列表。这基本上是:

# storing in data frames just for illustration, I would like to do this within the list
# subsets for the 3 predictor tables with the first response variable
aa <- merged_list[[1]][,-c(46:58)]  # column 1:44 are the predictor variables, then the different response variables start
bb <- merged_list[[2]][,-c(45:57)]  # column 1:43 are the predictor variables, then the different response variables start
cc <- merged_list[[3]][,-c(43:58)] # column 1:41 are the predictor variables, then the different response variables start

# subsets for the 3 predictor tables with the second response variable
dd <- merged_list[[1]][,-c(45, 47:58)]
ee <- merged_list[[2]][,-c(44, 46:57)]
ff <- merged_list[[3]][,-c(42, 44:58)]

# subsets for the 3 predictor tables with the third response variable
gg <- merged_list[[1]][,-c(45, 46, 48:58)]
...

# this is just to illustrate how the list could look like, I would like to keep all files in a list all the time
list_for_classification_runs <- list(aa, bb, cc, dd, ee, ff, gg, ...)

此结果列表将作为随机森林分类调用的输入,其中响应变量将由来自 varespec 的所有其他预测变量分类,例如:

for (current_table in list_for_classification_runs) {
  counter <- counter + 1 
  # response_variable should be the one variable added to the predictor variables in the data frames 
  RF_list[[counter]] <- ranger(response_variable ~ ., data = current_table)
}

【问题讨论】:

  • 啊抱歉,这只是示例代码中的一个问题,在我的原始数据中,merged_list 运行良好。我将更新代码并更好地解释我的预期输出是什么
  • 将所有这些数据帧存储在列表中似乎效率低下......看起来你可能更容易制作 1 个包含所有响应的大数据帧(或者可能是 3 个包含所有响应的大数据帧)并将不同的数据子集/不同的公式提供给ranger
  • 所以,基本上使用merged_list[[1]] 并给游侠data = merged_list[[1]][, c(1:44, i + 44),让i 变化从一个响应的数量。并类似地构造公式以使 LHS 是正确的。我只是认为没有必要将它们全部命名为aabb,...并将它们分别保存为单独的副本。
  • @Gregor:数据框来自许多不同的对象,但我可以想办法将它们组合起来。不过,我必须更改 row.names,因为在我的真实数据中它们在子集之间重叠。如果预测变量的数量始终相同,则遍历列的方式看起来不错。在我的真实数据中,它们会发生变化,我还希望通过按名称寻址来使它们更具可读性。我将为此调整示例数据,对不起,我什至没有考虑过这种影响

标签: r list


【解决方案1】:

基于 Gregor 的 cmets,我想出了一个类似的方法。我没有将完整的varechem_binarysubset_list 的所有元素合并,而是添加了另一个for 循环并遍历varechem_binary 中的所有列。使用drop = FALSE 保留row.names 和结构,因此合并工作:

merge_col_counter <- 0
column_counter <- 0
merged_column_list <- list()

for(table in subset_list) {
    merge_col_counter <- merge_col_counter + 1
    for (column in names(varechem_binary)) {
      column_counter <- column_counter + 1
      current_name <- paste(names(subset_list)[merge_col_counter], names(varechem_binary)[column_counter], sep = "_")
      print(current_name)
      tmp <- merge(table, varechem_binary[, column_counter, drop = FALSE], by = "row.names")
      row.names(tmp) <- tmp$Row.names
      tmp <- tmp[, -1]
      merged_column_list[[current_name]] <- tmp
      rm(tmp)
    }
    column_counter <- 0
}

可能有一些方法可以做到这一点更清洁或更高效,但它确实有效,所以我可以继续

【讨论】:

    【解决方案2】:

    使用应用函数的另一种解决方案:

    lapply(subset_list, function(x) apply(varechem_binary, 2, function(var) merge(var, x, by= 'row.names')))
    

    使用 system.time() 使用您的样本数据对这两种方法进行基准测试,这种方法的速度(0.075 用户时间)是使用 for 循环的解决方案(0.143 用户时间)的两倍。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-21
      • 2018-10-28
      • 2015-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-18
      • 2019-05-27
      相关资源
      最近更新 更多