对具有相似名称的列求和

Sum column with similar name

我在 R 中有一个像这样的数据集(我的真实数据集有更多的行和列):

AB1 AB3 AB4 XB1 XB3 XB4
12 34 0 5 3 7

我需要对类似的列求和

AB1+XB1 AB3+XB3 AB4+XB4

我可以使用什么代码?

试试这个:

library(tidyverse)

tribble(
  ~AB1, ~AB3, ~AB4, ~XB1, ~XB3, ~XB4,
  12, 34, 0, 5, 3, 7
) |> 
  pivot_longer(everything(), names_pattern = "(\w\w)(\d)", names_to = c("prefix", "suffix")) |> 
  pivot_wider(names_from = prefix) |> 
  rowwise() |> 
  mutate(sum = sum(c_across(- suffix)))
#> # A tibble: 3 × 4
#> # Rowwise: 
#>   suffix    AB    XB   sum
#>   <chr>  <dbl> <dbl> <dbl>
#> 1 1         12     5    17
#> 2 3         34     3    37
#> 3 4          0     7     7

reprex package (v2.0.1)

创建于 2022-05-11

假设是第一个变化的字符,其他的用来分组

df=read.table(text="
AB1 AB3 AB4 XB1 XB3 XB4
12  34  0   5   3   7
11  35  1   7   2   8",h=T)

sapply(
  unique(substr(colnames(df),2,100)),
  function(x){
    rowSums(df[,grepl(x,colnames(df))])
  }
)

     B1 B3 B4
[1,] 17 37  7
[2,] 18 37  9

使用注释中的第 2 行 DF2 作为输入计算后缀 (s)、唯一后缀 (u) 并执行指定的矩阵乘法给出 (m)。最后将其转换回数据框并设置名称。没有使用包。

s <- substring(names(DF2), 2)
u <- unique(s)
m <- as.matrix(DF2) %*% outer(s, u, `==`)
sums <- setNames(as.data.frame(m), u); sums
##   B1 B3 B4
## 1 17 37  7
## 2 17 37  7

如果需要将这些作为列附加到 DF2,则:

data.frame(DF2, sum = sums)
##   AB1 AB3 AB4 XB1 XB3 XB4 sum.B1 sum.B3 sum.B4
## 1  12  34   0   5   3   7     17     37      7
## 2  12  34   0   5   3   7     17     37      7

备注

DF <- structure(list(AB1 = 12L, AB3 = 34L, AB4 = 0L, XB1 = 5L, XB3 = 3L, 
    XB4 = 7L), class = "data.frame", row.names = c(NA, -1L))
DF2 <- rbind(DF, DF)

DF2
##   AB1 AB3 AB4 XB1 XB3 XB4
## 1  12  34   0   5   3   7
## 2  12  34   0   5   3   7

如果您知道结构是一致的(所有内容都是“A”和“X”对),那么这应该可行。

cols <- unique(substring(names(df), 2))
df[paste0("A", cols)] + df[paste0("X", cols)]

你可以使用

library(dplyr)
df %>% 
  mutate(across(starts_with("AB"),
                ~.x + df[[gsub("AB", "XB", cur_column())]],
                .names = "sum_{.col}"))

这个returns

# A tibble: 1 x 9
    AB1   AB3   AB4   XB1   XB3   XB4 sum_AB1 sum_AB3 sum_AB4
  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>   <dbl>   <dbl>   <dbl>
1    12    34     0     5     3     7      17      37       7
  • 我们在此方法中使用 acrossmutate
  • 首先我们 select 所有以 AB 开头的列。所需的总和始终为 ABn + XB2,因此我们可以使用此模式。
  • 接下来,我们将当前 selected 列名称中的 AB 替换为 XB 并将这两列相加。这些总和存储在以 sum_.
  • 为前缀的新列中

我们可以试试下面的代码

cbind(
    df,
    list2DF(lapply(
        split.default(df, gsub("\D+", "", names(df))),
        rowSums
    ))
)

这给出了

  AB1 AB3 AB4 XB1 XB3 XB4  1  3 4
1  12  34   0   5   3   7 17 37 7

across2 来自 dplyover

的选项
library(dplyover)
df1 %>%
  mutate(across2(starts_with('AB'), starts_with('XB'), 
     ~ .x + .y, .names = "sum_{xcol}"))
  AB1 AB3 AB4 XB1 XB3 XB4 sum_AB1 sum_AB3 sum_AB4
1  12  34   0   5   3   7      17      37       7