【问题标题】:R: Merging lists of data framesR:合并数据框列表
【发布时间】:2016-06-25 16:37:52
【问题描述】:

我是 R 的菜鸟,我已经尝试(并重试)寻找以下问题的答案,但我无法获得任何建议的解决方案来做我正在做的事情有兴趣。

我有两个命名元素列表,每个元素都指向具有相同布局的数据框:

(编辑)

df1 <- data.frame(A=c(1,2,3),B=c("A","B","C"))
df2 <- data.frame(A=c(98,99),B=c("Y","Z"))
lst1 <- c(X=df1,Y=df2)
df3 <- data.frame(A=c(4,5),B=c("D","E"))
lst2 <- c(X=df3)

(编辑 2)

因此,在一个列表中存储多个数据框似乎是个坏主意,因为它会将数据框转换为列表。所以我会出去寻找另一种方法来存储一组命名数据帧。

通常,两个元素中的元素名称可能部分重叠、完全重叠或根本不重叠。

我正在寻找一种将两个列表合并为一个列表的方法:

<some-function-sequence>(lst1, lst2)
->
c(X=rbind(df1,df3),Y=df2)

-导致这样的事情:

[编辑:语法已更改以正确反映所需的结果(数据帧列表)] $X 甲乙 1 1 安 2 2 乙 3 3℃ 4 4 天 5 5 E

$X.B
   A B
1 98 Y
2 99 Z

即:

  • 如果列表包含相同的元素名称,每个都指向一个数据框,那么我想“绑定”这两个数据框中的行,并将结果数据框分配给结果列表中的相同元素名称。李>
  • 否则,两个列表中的元素名称和数据框应仅复制到结果列表中。

我已经尝试了许多讨论中的解决方案,例如:

-但我一直无法找到正确的解决方案。一个普遍的问题似乎是数据框最终被“mapply/sapply/merge/...”的应用程序转换为一个列表 - 而且通常还以我不感兴趣的方式切片和/或合并。 :)

对此的任何帮助将不胜感激!

[解决方案] 解决方案似乎是在收集数据帧时将c(...)的使用更改为list(...),之后Pierre提出的解决方案似乎给出了预期的结果。

【问题讨论】:

  • 花一些时间来创建一些示例数据框。伪代码不够具体,无法描述您正在使用的内部结构。 c(a=&lt;data-frame-1&gt;,.. 会将数据框分解为每列的列表元素。我怀疑你的真实数据反映了这一点。
  • 如果您将数据存储在 list(a=df1, b=df2) 中的列表中,那么您可以使用 split 和 rbind lapply(split(c(lst1, lst2), names(c(lst1,lst2))), function(lst) do.call(rbind, lst))
  • 感谢您的回复皮埃尔。我已经在上面尝试了您的建议,但无法使其正常工作。我在我的问题中添加了一些示例数据以及在其上运行命令的结果。
  • 请再次阅读我的建议。 “如果您将数据存储在 LISTS 中,如 LIST!!!(a=df1, b=df2)”。你有没有费心阅读那部分?看看你的代码,告诉我你有没有。当您没有我要求的表格中的数据时,为什么要使用我的解决方案?您希望它如何工作?
  • 你知道c(df1, df2) 对数据帧做了什么吗?它打破了数据框。

标签: r list merge mapply


【解决方案1】:

以下解决方案可能不是最有效的方法。但是,如果我解决了您的问题,这应该可以;)

# Example data

# Some vectors
a <- 1:5
b <- 3:7
c <- rep(5, 5)
d <- 5:1

# Some dataframes, data1 and data3 have identical column names
data1 <- data.frame(a, b)
data2 <- data.frame(c, b)
data3 <- data.frame(a, b)
data4 <- data.frame(c, d)

# 2 lists
list1 <- list(data1, data2)
list2 <- list(data3, data4)

# Loop, wich checks for the dataframe names and rbinds dataframes with the same column names
final_list <- list1
used_lists <- numeric()

for(i in 1:length(list1)) {

    for(j in 1:length(list2)) {

    if(sum(colnames(list1[[i]]) == colnames(list2[[j]])) == ncol(list1[[i]])) {

      final_list[[i]] <- rbind(list1[[i]], list2[[j]])
      used_lists <- c(used_lists, j)

    }
  }
}

# Adding the other dataframes, which did not have the same column names
for(i in 1:length(list2)) {

  if((i %in% used_lists) == FALSE) {

    final_list[[length(final_list) + 1]] <- list2[[i]]

  }
}

# Final list, which includes all other lists
final_list

【讨论】:

  • 感谢您的回复。不幸的是,在我的示例数据上运行您的代码时,我得到了以下结果:list1 &lt;- lst1 list2 &lt;- lst2 (...) Error in if (sum(colnames(list1[[i]]) == colnames(list2[[j]])) == ncol(list1[[i]])) { : argument is of length zero
  • 如果你想创建一个数据框列表,你必须写 list(df1, df2) 而不是 c(df1, df2)。如果你这样做,我的代码应该可以工作。
【解决方案2】:

这是使用splitc 组合类似术语的建议解决方案。请阅读底部的警告:

s <- split(c(lst1, lst2), names(c(lst1,lst2))) 
lapply(s, function(lst) do.call(function(...) unname(c(...)), lst))
# $X.A
# [1] 1 2 3 4 5
# 
# $X.B
# [1] "A" "B" "C" "D" "E"
# 
# $Y.A
# [1] 98 99
# 
# $Y.B
# [1] "Y" "Z"

此解决方案基于不将因子作为字符串。它不会抛出错误,但因子将转换为数字。下面我展示了我如何转换数据以消除因素。如果您需要因素,请告诉我:

df1 <- data.frame(A=c(1,2,3),B=c("A","B","C"), stringsAsFactors=FALSE)
df2 <- data.frame(A=c(98,99),B=c("Y","Z"), stringsAsFactors=FALSE)
lst1 <- c(X=df1,Y=df2)
df3 <- data.frame(A=c(4,5),B=c("D","E"), stringsAsFactors=FALSE)
lst2 <- c(X=df3)

如果数据存储在我们可以使用的列表中:

lapply(split(c(lst1, lst2), names(c(lst1,lst2))), function(lst) do.call(rbind, lst))

【讨论】:

    猜你喜欢
    • 2018-05-20
    • 1970-01-01
    • 2015-11-06
    • 1970-01-01
    • 2019-03-24
    • 2020-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-10
    相关资源
    最近更新 更多