如何对动态 R 列表中的嵌入数据帧列求和?

How sum embedded dataframe columns in a dynamic R list?

提问人:Village.Idyot 提问时间:8/3/2023 更新时间:8/3/2023 访问量:39

问:

我正在学习使用列表。

如何在具有嵌入式数据帧的动态列表中添加所有列,例如,我想对名称以 ?例如,在下面,函数或公式将返回一个向量 (7,9,11,13,15),表示子列表和子列表“First.allocation”列的列式和。First.allocationSyriaList1Syria_OneSyria_Two

再举一个例子,在下面,函数或公式将返回一个向量 (1,2,3,4,5),表示列表中唯一以“Syria”开头的子列表的列。List2First.allocation

List1 <- list(
  Syria_One = data.frame(
    First.allocation = c(1,2,3,4,5),
    Second.numerator = rep(0,5),
    Second.allocation = rep(0,5)
  ),
  Syria_Two = data.frame(
    First.allocation = c(6,7,8,9,10),
    Second.numerator = rep(0,5),
    Second.allocation = rep(0,5)
  ),
  Tunisia = data.frame(
    First.allocation = rep(0.2,5),
    Second.numerator = rep(0,5),
    Second.allocation = rep(0,5)
  ),
  Total = data.frame(
    First.allocation = rep(1,5),
    Second.numerator = rep(0,5),
    Second.allocation = rep(0,5)
  )
)

List2 <- list(
  Syria_One = data.frame(
    First.allocation = c(1,2,3,4,5),
    Second.numerator = rep(0,5),
    Second.allocation = rep(0,5)
  ),
  Tunisia = data.frame(
    First.allocation = rep(0.2,5),
    Second.numerator = rep(0,5),
    Second.allocation = rep(0,5)
  ),
  Total = data.frame(
    First.allocation = rep(1,5),
    Second.numerator = rep(0,5),
    Second.allocation = rep(0,5)
  )
)
r 列表 嵌套列表

评论


答:

2赞 jpsmith 8/3/2023 #1

可能有更优雅的方法,但一种方法是用于获取所需的列(用于隔离带有“Syria”的列),然后用于列,最后获得总和:lapplygrepdo.callcbindrowSums

rowSums(do.call(cbind, lapply(List1[grepl("Syria", names(List1))], function(x) x[,1])))

# [1]  7  9 11 13 15

为了分解这一点,因为上面的内容可能有点令人困惑:

syria <- grepl("Syria", names(List1))
# [1]  TRUE  TRUE FALSE FALSE

List_Syria <- List1[syria]

#$Syria_One
#  First.allocation Second.numerator Second.allocation
#1                1                0                 0
#2                2                0                 0
#3                3                0                 0
#4                4                0                 0
#5                5                0                 0
#
#$Syria_Two
#  First.allocation Second.numerator Second.allocation
#1                6                0                 0
#2                7                0                 0
#3                8                0                 0
#4                9                0                 0
#5               10                0                 0

test1 <- lapply(List_Syria, function(x) x[,1])

#$Syria_One
#[1] 1 2 3 4 5
#
#$Syria_Two
#[1]  6  7  8  9 10

test2 <- do.call(cbind, test1)

#     Syria_One Syria_Two
#[1,]         1         6
#[2,]         2         7
#[3,]         3         8
#[4,]         4         9
#[5,]         5        10

rowSums(test2)
#[1]  7  9 11 13 15
3赞 Darren Tsai 8/3/2023 #2

为了动态地处理这个问题,你可以定义一个具有 2 个参数的函数:

  • regex:列表名称的正则表达式
  • col:列名(或索引)
fun <- function(lst, regex = "^Syria", col = 1) {
  Reduce(`+`, lapply(lst[grepl(regex, names(lst))], `[[`, col))
}

fun(List1)
# [1]  7  9 11 13 15

fun(List2)
# [1] 1 2 3 4 5

如果要操作除“Syria”以外的其他列表,或除“First.allocation”以外的其他列,可以在调用时修改这些参数。fun()

0赞 LMc 8/3/2023 #3

您可以对同名元素求和(其中类似命名表示最后一个元素之前的前缀):_

f <- function(l) {
split(names(l), gsub("_.*", "", names(l))) |>
  lapply(\(x) Reduce(`+`, l[x]))
}

f(List1)

$Syria
  First.allocation Second.numerator Second.allocation
1                7                0                 0
2                9                0                 0
3               11                0                 0
4               13                0                 0
5               15                0                 0

$Total
  First.allocation Second.numerator Second.allocation
1                1                0                 0
2                1                0                 0
3                1                0                 0
4                1                0                 0
5                1                0                 0

$Tunisia
  First.allocation Second.numerator Second.allocation
1              0.2                0                 0
2              0.2                0                 0
3              0.2                0                 0
4              0.2                0                 0
5              0.2                0                 0

然后,您可以简单地访问所需的任何元素和列:

f(List1)$Syria$First.allocation
# [1]  7  9 11 13 15

如果您在同一列表中还有“Tunisia_One”和“Tunisia_Two”等,则这足够灵活。