列表列表中元素的平均值

Posted

技术标签:

【中文标题】列表列表中元素的平均值【英文标题】:Mean of an element in list of lists 【发布时间】:2021-09-30 01:30:33 【问题描述】:

我有一个列表列表,其中每个列表都包含代码(名称)及其值。对于每个列表,这些代码保持不变,但值不同。现在,我想看看这些代码的平均值是多少。问题是我不知道如何指定查看每个列表中的特定代码并提取值。例如,我想要这 3 个列表中“jpm”的平均值。应该是mean(c(0.08620690,0.10000000,0.10000000)) = 0.095402。我该怎么做?

到目前为止我所拥有的:

dput(degree.l)
list(c(schwab = 0, pnc = 0.0344827586206897, jpm = 0.0862068965517241, 
amex = 0.0862068965517241, gs = 0.103448275862069, ms = 0.103448275862069, 
bofa = 0.103448275862069, citi = 0.103448275862069, wf = 0.120689655172414, 
spgl = 0.120689655172414, brk = 0.137931034482759), c(schwab = 0.0166666666666667, 
pnc = 0.05, ms = 0.0666666666666667, spgl = 0.0833333333333333, 
jpm = 0.1, bofa = 0.1, wf = 0.1, amex = 0.1, gs = 0.116666666666667, 
brk = 0.116666666666667, citi = 0.15), c(schwab = 0.0428571428571429, 
gs = 0.0714285714285714, pnc = 0.0714285714285714, citi = 0.0857142857142857, 
amex = 0.0857142857142857, spgl = 0.0857142857142857, jpm = 0.1, 
brk = 0.1, ms = 0.114285714285714, wf = 0.114285714285714, bofa = 0.128571428571429
))

degree.unl <- unlist(degree.l)

【问题讨论】:

【参考方案1】:

我们可以在base R 中使用aggregatestack

aggregate(values ~ ind, do.call(rbind, lapply(degree.l, stack)), FUN = mean)

-输出

  ind     values
1  schwab 0.01984127
2     pnc 0.05197044
3     jpm 0.09540230
4    amex 0.09064039
5      gs 0.09718117
6      ms 0.09480022
7    bofa 0.11067323
8    citi 0.11305419
9      wf 0.11165846
10   spgl 0.09657909
11    brk 0.11819923

或者另一种选择是Reduce(假设没有NA)进行元素加法(+)并除以listlength

 Reduce(`+`, degree.l)/length(degree.l)
    schwab        pnc        jpm       amex         gs         ms       bofa       citi         wf       spgl        brk 
0.01984127 0.05197044 0.07476738 0.08508484 0.09638752 0.09638752 0.10114943 0.10114943 0.11721401 0.11721401 0.13883415 

或者作为 OP unlisted 数据集,然后使用该对象,按 names 分组并使用 tapply

tapply(degree.unl, names(degree.unl), FUN = mean)
      amex       bofa        brk       citi         gs        jpm         ms        pnc     schwab       spgl         wf 
0.09064039 0.11067323 0.11819923 0.11305419 0.09718117 0.09540230 0.09480022 0.05197044 0.01984127 0.09657909 0.11165846 

【讨论】:

第一个和最后一个工作,最后一个真的很棒!第二个虽然对其他人没有相同的价值。那是因为代码的位置不固定。谢谢! @statwoman 第二种解决方案有两个假设要满足 1) 没有缺失 (NA) 值,2) 每个元素的长度相同且顺序相同【参考方案2】:

另一种选择:

get_ticker <- function(t) mean(sapply(d, "[[", t))
sapply(names(degree.l[[1]]), get_ticker)

【讨论】:

【参考方案3】:

unlisting 之前,

apply(do.call(rbind, degree.l), 2, mean)
#     schwab        pnc        jpm       amex         gs         ms       bofa 
# 0.01984127 0.05197044 0.07476738 0.08508484 0.09638752 0.09638752 0.10114943 
#       citi         wf       spgl        brk 
# 0.10114943 0.11721401 0.11721401 0.13883415 

编辑:既然你说你不能假设代码是有序的,我们可以解决这个问题:

nms <- unique(unlist(lapply(degree.l, names)))
nms
#  [1] "schwab" "pnc"    "jpm"    "amex"   "gs"     "ms"     "bofa"   "citi"  
#  [9] "wf"     "spgl"   "brk"   

apply(do.call(rbind, lapply(degree.l, `[`, nms)), 2, mean)
#     schwab        pnc        jpm       amex         gs         ms       bofa 
# 0.01984127 0.05197044 0.09540230 0.09064039 0.09718117 0.09480022 0.11067323 
#       citi         wf       spgl        brk 
# 0.11305419 0.11165846 0.09657909 0.11819923 

为了好玩,我们可以将它们混为一谈以确认它是否有效:

set.seed(42)
degree.l.jumbled <- lapply(degree.l, sample)
degree.l.jumbled
# [[1]]
#     schwab         gs        brk         wf        pnc       amex       bofa 
# 0.00000000 0.10344828 0.13793103 0.12068966 0.03448276 0.08620690 0.10344828 
#       spgl       citi         ms        jpm 
# 0.12068966 0.10344828 0.10344828 0.08620690 
# [[2]]
#       amex         wf       spgl     schwab        jpm       bofa         gs 
# 0.10000000 0.10000000 0.08333333 0.01666667 0.10000000 0.10000000 0.11666667 
#        pnc        brk       citi         ms 
# 0.05000000 0.11666667 0.15000000 0.06666667 
# [[3]]
#         ms       bofa       citi       amex        jpm        brk       spgl 
# 0.11428571 0.12857143 0.08571429 0.08571429 0.10000000 0.10000000 0.08571429 
#         wf         gs        pnc     schwab 
# 0.11428571 0.07142857 0.07142857 0.04285714 
apply(do.call(rbind, lapply(degree.l.jumbled, `[`, nms)), 2, mean)
#     schwab        pnc        jpm       amex         gs         ms       bofa 
# 0.01984127 0.05197044 0.09540230 0.09064039 0.09718117 0.09480022 0.11067323 
#       citi         wf       spgl        brk 
# 0.11305419 0.11165846 0.09657909 0.11819923 

【讨论】:

所以这是不正确的,因为例如“jpm”代码并不总是在同一个地方。但我实际上可以将它们按相同的顺序排列,这样它就可以工作了。谢谢! 已修复,请参阅我的编辑。公平地说,您在此处的评论与您声明“这些代码在每个列表中保持相同” 的问题相反。要么保持不变,要么不保持不变,您需要明确问题,清楚地了解样本数据,并在评估结果时保持一致。【参考方案4】:

data.table 选项使用 rbindlist + colMeans

> colMeans(rbindlist(Map(function(x) data.frame(t(x)), degree.1), use.names = TRUE))
    schwab        pnc        jpm       amex         gs         ms       bofa
0.01984127 0.05197044 0.09540230 0.09064039 0.09718117 0.09480022 0.11067323
      citi         wf       spgl        brk
0.11305419 0.11165846 0.09657909 0.11819923

然后,如果您想用任何名称检索平均值,例如,schwab,您可以尝试如下所示

colMeans(rbindlist(Map(function(x) data.frame(t(x)), degree.1), use.names = TRUE))["schwab"]

【讨论】:

以上是关于列表列表中元素的平均值的主要内容,如果未能解决你的问题,请参考以下文章

列表中元素的平均值

Python:计算具有不同长度的列表列表中第 n 个元素的平均值

两个独立数据框列表中所有元素的平均值和标准差

如何计算python字典中列表元素的平均值?

python中列表增加元素的方法

散列表的平均查找长度怎么计算?