首页 > 解决方案 > R - 使用父子关系表计算总数

问题描述

我正在使用一个包含两个表的数据集:一个给出最低级别的多个变量的值,另一个显示我应该用来计算总数的所有子父关系。

我的数据看起来像这样:

> # table that shows child-parent relation
> ID <- c(5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
> PARENT_ID <- c(NA, 5, 10, 10, 5, 5, 5, 60, 60, 60, 60)
> df_relation <- data.frame(ID, PARENT_ID)
> df_relation
    ID PARENT_ID
1    5        NA
2   10         5
3   20        10
4   30        10
5   40         5
6   50         5
7   60         5
8   70        60
9   80        60
10  90        60
11 100        60
> # For instance, ID 70 + 80 + 90 + 100 gives the value for ID 60
> 
> # table that contains values at the lowest level
> ID <- c(20, 30, 40, 50, 70, 80, 90, 100)
> VALUE <- c(14, 1, 4329, 98503, 272, 667, 712, 55)
> df_value <- data.frame(ID, VALUE)
> df_value
   ID VALUE
1  20    14
2  30     1
3  40  4329
4  50 98503
5  70   272
6  80   667
7  90   712
8 100    55
> 
> # add values to relation table
> df <- left_join(df_relation, df_value, by = "ID")
> df
    ID PARENT_ID VALUE
1    5        NA    NA
2   10         5    NA
3   20        10    14
4   30        10     1
5   40         5  4329
6   50         5 98503
7   60         5    NA
8   70        60   272
9   80        60   667
10  90        60   712
11 100        60    55
> 
> # compute totals (ID = 5, 10 & 60)
> # ID 60 = 70 + 80 + 90 + 100
> # ID 10 = 20 = 30
> # ID 5 = 10 + 40 + 50 + 60 

当然,我可以手动执行此操作,但我还有许多具有更多子父级别的附加表。所以我宁愿有一个可以完成这项工作的功能。有人知道该怎么做吗?

标签: r

解决方案


看起来您需要在这里使用递归:

sum_children <- function(ID, data)
{
  result <- 0;
  children <- which(data$PARENT_ID == ID)
  if(length(children) == 0) 
    return(data$VALUE[which(data$ID == ID)])
  else 
    for(i in seq_along(children)) 
      result <- result + sum_children(data$ID[children[i]], data)
  return(result)
}

此函数将采用您希望计算其子总和的 ID 并返回结果。

sum_children(60, df)
#> [1] 1706

它将工作到任何深度。例如,您的示例中每个具有值的节点最终都从 ID 5 下降。因此,5 的子总和应该与总和相同VALUE

sum(df$VALUE, na.rm = T)
#> [1] 104553

sum_children(5, df)
#> [1] 104553

事实上,您可以通过执行以下操作快速获取每个 ID 的所有后代的结果:

df$child_sum <- sapply(df$ID, sum_children, df)

df
#>     ID PARENT_ID VALUE child_sum
#> 1    5        NA    NA    104553
#> 2   10         5    NA        15
#> 3   20        10    14        14
#> 4   30        10     1         1
#> 5   40         5  4329      4329
#> 6   50         5 98503     98503
#> 7   60         5    NA      1706
#> 8   70        60   272       272
#> 9   80        60   667       667
#> 10  90        60   712       712
#> 11 100        60    55        55

推荐阅读