Sum by aggregating complex paired names in R
在 R 中,我尝试根据唯一 ID 聚合数据帧,但我需要为 ID 使用某种通配符值。这意味着我有这样的配对名称:
1 2 3 | lion_tiger elephant_lion tiger_lion |
我需要将 lion_tiger 和 tiger_lion ID 相加,因为这对中的顺序无关紧要。
以这个数据框为例:
1 2 | df <- data.frame(pair = c("1_3","2_4","2_2","1_2","2_1","4_2","3_1","4_3","3_2"), value = c("12","10","19","2","34","29","13","3","14")) |
因此,对 ID、"1_2" 和 "2_1" 的值需要在一个新表中求和。然后该新行将显示为:
1 | 1_2 36 |
有什么建议吗?虽然我的示例将数字作为配对 ID,但实际上我需要将其读取为文本(如上面的 lion_tiger" 示例)。
我们可以用
1 2 3 | tapply(as.numeric(as.character(df$value)), sapply(strsplit(as.character(df$pair), '_'), function(x) paste(sort(as.numeric(x)), collapse="_")), FUN = sum) |
或者另一个选项是
1 2 3 4 5 | library(gsubfn) df$pair <- gsubfn('([0-9]+)_([0-9]+)', ~paste(sort(as.numeric(c(x, y))), collapse='_'), as.character(df$pair)) df$value <- as.numeric(as.character(df$value)) aggregate(value~pair, df, sum) |
使用 tidyverse 和 purrrlyr
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | df <- data.frame(name=c("lion_tiger","elephant_lion", "tiger_lion"),value=c(1,2,3),stringsAsFactors=FALSE) require(tidyverse) require(purrrlyr) df %>% separate(col = name, sep ="_", c("A","B")) %>% by_row(.collate ="rows", ..f = function(this_row) { paste0(sort(c(this_row$A, this_row$B)), collapse ="_") }) %>% rename(sorted =".out") %>% group_by(sorted) %>% summarize(sum(value))%>%show ## A tibble: 2 x 2 # sorted `sum(value)` # <chr> <dbl> #1 elephant_lion 2 #2 lion_tiger 4 |