首页 > 解决方案 > R - 合并分布在数据帧列表中的标识符值

问题描述

我有一个数据框列表

df1 <- data.frame(Symbol = c("A", "A", "B", "C", "D", "D", "D", "E", "E", "A"),
                     Sample1 = sample(50, 10),
                     Sample2 = sample(50, 10),
                     Sample3 = sample(50, 10))
df2 <- data.frame(Symbol = c("B", "B", "B", "E", "A"),
                  Sample4 = sample(50, 5),
                  Sample5 = sample(50, 5),
                  Sample6 = sample(50, 5))
df3 <- data.frame(Symbol = c("A", "B", "C", "D", "E", "F"),
                  Sample7 = sample(50, 6),
                  Sample8 = sample(50, 6),
                  Sample9 = sample(50, 6))

如您所见,每个数据框都有一个名为 的列Symbol,其中包含出现在列表中多个数据框的值。我希望能够合并它们,这样我就可以选择一些基本的统计数据(例如平均值、第 25 个百分位数等)。最初,我只是这样做

dfList <- list(df1, df2, df3)
df <- reduce(dfList, merge, "Symbol", all = T)

以为我只是取每一行的平均值。但是,我不知道符号在每个数据框中多次出现。所以上面的行实际上合并A了第一个数据帧中每个出现的say,A以及第二个和第三个数据帧中的每个出现。这不是我想要的。

Symbol混乱的解决方案是从整个列表中获取唯一标识符,然后lapply在它们上面写一个,我在其中搜索每个数据帧中的每个标识符,并提取值。然后我会有一个向量列表,名称是符号标识符。像这样的东西

syms <- unique(as.character(unlist(lapply(dfList, function(x) return(x$Symbol)))))
lst <- lapply(syms, function(x) {
  return(unlist(lapply(dfList, function(y) {
    return(unlist(y[grep(x, y$Symbol),-1]))
  })))
})
names(lst) <- syms

然后我可以取平均值,中位数等......

这在我的实际数据帧上非常慢,我只是认为必须有一种更简单的方法来做到这一点。

编辑:所以最后,我想要这样的东西:

Mean = t(as.data.frame(lapply(lst, function(x) {
  return(mean(x))
})))
Min = t(as.data.frame(lapply(lst, function(x) {
  return(min(x))
})))
Quantiles = t(as.data.frame(lapply(lst, function(x) {
  return(quantile(x, c(0.25, 0.5, 0.75)))
})))
Max = t(as.data.frame(lapply(lst, function(x) {
  return(max(x))
})))
df <- cbind(Mean, Min, Quantiles, Max)
colnames(df) <- c("Mean", "Min", "p25", "p50", "p75", "Max")

这将产生

> df
      Mean Min   p25  p50   p75 Max
A 27.53333  13 21.50 27.0 32.50  48
B 24.33333   2 11.00 21.0 37.50  48
C 26.50000   3 24.00 26.5 32.75  45
D 25.00000   2 12.25 23.5 38.75  49
E 23.25000   2 12.75 22.0 33.75  45
F 21.00000  11 11.50 12.0 26.00  40

标签: rlistdataframe

解决方案


考虑通过Symbol进行链合并,然后是从宽格式到长格式以及跨多个函数:reshapeaggregate

# MERGE ALL BY Symbol
dfList <- list(df1, df2, df3)
mdf <- Reduce(function(...) merge(..., by="Symbol", all=TRUE), dfList)

# RESHAPE WIDE TO LONG
rdf <- reshape(mdf, varying=names(mdf)[-1], times=names(mdf)[-1],
               v.name = "Value", timevar="Sample",
               new.row.names = 1:1E4, direction = "long")

# AGGREGATE DATA
agg_raw <- aggregate(Value ~ Symbol, rdf, 
                     function(x) c(Mean=mean(x), Min=min(x), p25=unname(quantile(x)[2]), 
                                   p50=median(x), p75=unname(quantile(x)[4]), Max=max(x)))

agg_df <- do.call(data.frame, agg_raw)
colnames(agg_df) <- gsub("Value.", "", colnames(agg_df))
agg_df

#   Symbol     Mean Min   p25  p50   p75 Max
# 1      A 30.77778   3 26.00 33.0 38.00  47
# 2      B 25.29630   3 16.00 23.0 30.50  47
# 3      C 23.00000   4 14.25 24.0 33.75  38
# 4      D 30.77778   2 17.75 34.0 43.00  49
# 5      E 25.38889   3 15.00 22.5 39.75  50
# 6      F 15.66667  13 13.00 13.0 17.00  21

Rextester 演示


推荐阅读