繁体   English   中英

R:按组对嵌入在 Dataframe 的行中的两个列表求和

[英]R: Sum Two Lists Embedded in Rows of a Dataframe by Groups

我有关于债券组及其现金流量的数据。 每个 IssueID 包含多个 BondID。 每个 BondID 都有自己的现金流,通过 dplyr 变异在数据框中呈现为列表。 现金流量列表没有相同数量的元素。 数据结构为:

问题ID 债券编号 现金周转
AA AA1 c(-1000, 50, 50, 1050)
AA AA2 c(-1000, 25, 25, 25, 25, 1025)
AB AB1 c(-2000, 100, 100, 2100)
AB AB1 c(-1000, 75, 75, 75, 75, 1075)

我需要按 IssueID 对每个 BondID 的现金流求和,同时在列表中维护每个元素的 position。 output 需要看起来像:

问题ID 总现金流量
AA c(-2000, 75, 75, 1075, 25, 1025)
AB c(-3000, 175, 175, 2175, 75, 1075)

感谢任何帮助。 谢谢。

我无法总结列表。

这是一个选项 - 按“IssueID”分组,将cashflow列表转换为带序列的命名listrow_number() ),然后使用enframe转换为unnest ,取消list列的嵌套,按“名称”的rowid创建分组'(如果长度不等),并获取'value'的sum ,将列作为list pull

library(dplyr)
library(tibble)
library(tidyr)
library(data.table)
out <- df1 %>%
  group_by(IssueID) %>%
  summarise(sumcashflow = setNames(cashflow, row_number()) %>%
         enframe %>%
         unnest(value) %>%
         group_by(grp = rowid(name)) %>%
         summarise(value = sum(value, na.rm = TRUE)) %>%
         pull(value) %>%
        list(.))

-输出

> out$sumcashflow
[[1]]
[1] -2000    75    75  1075    25  1025

[[2]]
[1] -3000   175   175  2175    75  1075

> out
# A tibble: 2 × 2
  IssueID sumcashflow
  <chr>   <list>     
1 AA      <dbl [6]>  
2 AB      <dbl [6]>  

或使用base R split

lst1 <- lapply(split(df1$cashflow, df1$IssueID), \(x) {
      mx <- max(lengths(x))
     rowSums(sapply(x, `length<-`, mx), na.rm = TRUE)
})

> lst1
$AA
[1] -2000    75    75  1075    25  1025

$AB
[1] -3000   175   175  2175    75  1075

数据

df1 <- structure(list(IssueID = c("AA", "AA", "AB", "AB"), BondID = c("AA1", 
"AA2", "AB1", "AB1"), cashflow = list(c(-1000, 50, 50, 1050), 
    c(-1000, 25, 25, 25, 25, 1025), c(-2000, 100, 100, 2100), 
    c(-1000, 75, 75, 75, 75, 1075))), row.names = c(NA, -4L), class = c("tbl_df", 
"tbl", "data.frame"))
df1 %>%
  group_by(IssueID) %>%
  summarise(val = list(colSums(do.call(qpcR:::rbind.na, cashflow), na.rm = TRUE)))

# A tibble: 2 x 2
  IssueID val      
  <chr>   <list>   
1 AA      <dbl [6]>
2 AB      <dbl [6]>

val:

[[1]]
[1] -2000    75    75  1075    25  1025

[[2]]
[1] -3000   175   175  2175    75  1075

可以写一个小的function,应用到每个IssueID

f <- function(cf) {
  ml = lengths(cf)
  for(i in seq_along(ml)) {
    if(length(cf[[i]])<max(ml)) cf[[i]]=c(cf[[i]],rep(0,max(ml)-length(cf[[i]])))
  }
  list(rowSums(matrix(unlist(cf),ncol=length(cf))))
}

使用dplyr

d %>% group_by(IssueID) %>% summarize(sumcashflow = f(cashflow))

使用data.table

setDT(d)[,.(f(cashflow)), by=IssueID]

Output:

   IssueID                         sumcashflow
1:      AA -2000,   75,   75, 1075,   25, 1025
2:      AB -3000,  175,  175, 2175,   75, 1075

输入:

d = data.table(
    IssueID = c("AA","AA","AB","AB"),
    BondID = c("AA1", "AA2","AB1", "AB2"),
    cashflow = list(c(-1000,50,50,1050),
                    c(-1000,25,25,25,25,1025),
                    c(-2000,100,100,2100),
                    c(-1000,75,75,75,75,1075))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM