首页 > 解决方案 > 在超过 50 列的 sum 命令中使用 R 语法序列运算符“:”

问题描述

我想使用序列运算符在 sum 命令中按列名索引。

library(dbplyr)
library(tidyverse)

df=data.frame(
  X=c("A","B","C"),
  X.1=c(1,2,3),X.2=c(1,2,3),X.3=c(1,2,3),X.4=c(1,2,3),X.5=c(1,2,3),X.6=c(1,2,3),X.7=c(1,2,3),X.8=c(1,2,3),X.9=c(1,2,3),X.10=c(1,2,3),
  X.11=c(1,2,3),X.12=c(1,2,3),X.13=c(1,2,3),X.14=c(1,2,3),X.15=c(1,2,3),X.16=c(1,2,3),X.17=c(1,2,3),X.18=c(1,2,3),X.19=c(1,2,3),X.20=c(1,2,3),
  X.21=c(1,2,3),X.22=c(1,2,3),X.23=c(1,2,3),X.24=c(1,2,3),X.25=c(1,2,3),X.26=c(1,2,3),X.27=c(1,2,3),X.28=c(1,2,3),X.29=c(1,2,3),X.30=c(1,2,3),
  X.31=c(1,2,3),X.32=c(1,2,3),X.33=c(1,2,3),X.34=c(1,2,3),X.35=c(1,2,3),X.36=c(1,2,3),X.37=c(1,2,3),X.38=c(1,2,3),X.39=c(1,2,3),X.40=c(1,2,3),
  X.41=c(1,2,3),X.42=c(1,2,3),X.43=c(1,2,3),X.44=c(1,2,3),X.45=c(1,2,3),X.46=c(1,2,3),X.47=c(1,2,3),X.48=c(1,2,3),X.49=c(1,2,3),X.50=c(1,2,3),
  X.51=c(1,2,3),X.52=c(1,2,3),X.53=c(1,2,3),X.54=c(1,2,3),X.55=c(1,2,3),X.56=c(1,2,3))

有没有更快的方法来做到这一点。以下提供了正确的结果。但是,对于大型数据集(大于此数据集),处理起来会变得很费力,尤其是在使用 pivot_wider 并且未事先创建列时(如上)

df %>% rowwise() %>% mutate(
  Result_column=case_when(
    X=="A"~ sum(c(X.1,X.2,X.3,X.4,X.5)),
    X=="B"~ sum(c(X.4,X.5)),
    X=="C" ~ sum(c( X.3,    X.4,    X.5,    X.6,    X.7,    X.8,    X.9,    X.10,   X.11,   X.12,   X.13,   X.14,   X.15,   X.16,   
                    X.17,   X.18,   X.19,   X.20,   X.21,   X.22,   X.23,   X.24,   X.25,   X.26,   X.27,   X.28,   X.29,   X.30,   
                    X.31,   X.32,   X.33,   X.34,   X.35,   X.36,   X.37,   X.38,   X.39,   X.40,   X.41,   X.42,X.43,  X.44,
                    X.45,   X.46,   X.47,   X.48,   X.49,   X.50,   X.51,   X.52,   X.53,   X.54,   X.55,   X.56))))  %>% dplyr::select(Result_column)          

以下是使用“选择”语法时的使用方式,这是我想使用的。但是,不提供正确的数值解。通过使用序列运算符“:”,可以将代码缩短约 50 个条目。

df %>% rowwise() %>% mutate(
  Result_column=case_when(
    X=="A"~ sum(c(X.1:X.5)),
    X=="B"~ sum(c(X.4:X.5)),
    X=="C" ~ sum(c(X.3:X.56)))) %>% dplyr::select(Result_column)

下面是一个相关的问题,但是,不一样,因为需要的不是以“X”开头的列,而是一个序列。 在列的子集上使用 mutate rowwise

编辑:cnbrowlie 提供的代码(如下)是正确的。

df %>%  mutate(
  Result_column=case_when(
    X=="A"~ sum(c(X.1:X.5)),
    X=="B"~ sum(c(X.4:X.5)),
    X=="C" ~ sum(c(X.3:X.56)))) %>% dplyr::select(Result_column)

标签: rsyntax

解决方案


这可以通过dplyr>=1.0.0 使用rowSums()(计算跨多列的行的总和)和across()(取代vars()作为指定数据帧中的列的方法,允许使用:来选择列序列)来完成:

df %>% rowwise() %>% mutate(
  Result_column=case_when(
    X=="A"~ rowSums(across(X.1:X.5)),
    X=="B"~ rowSums(across(X.4:X.5)),
    X=="C" ~ rowSums(across(X.3:X.56))
    )
  ) %>% dplyr::select(Result_column)

推荐阅读