Effectief optellen over meerdere kolommen in R

Ik heb de volgende gecomprimeerde dataset:

a<-as.data.frame(c(2000:2005))
a$Col1<-c(1:6)
a$Col2<-seq(2,12,2)
colnames(a)<-c("year","Col1","Col2")
for (i in 1:2){
  a[[paste("Var_", i, sep="")]]<-i*a[[paste("Col", i, sep="")]]
}

Ik wil graag de kolommen Var1 en Var2, die ik gebruik, optellen:

a$sum<-a$Var_1 + a$Var_2

In werkelijkheid is mijn dataset veel groter – ik zou willen optellen van Var_1 tot Var_n (n kan oplopen tot 20). Er moet een efficiëntere manier zijn om dit te doen dan:

a$sum<-a$Var_1 + ... + a$Var_n

Antwoord 1, autoriteit 100%

Hier is een oplossing met behulp van de tidyverse. U kunt het uitbreiden naar zoveel kolommen als u wilt door de functie select()te gebruiken om de juiste kolommen te selecteren binnen een mutate().

library(tidyverse)
a<-as.data.frame(c(2000:2005))
a$Col1<-c(1:6)
a$Col2<-seq(2,12,2)
colnames(a)<-c("year","Col1","Col2")
for (i in 1:2){
    a[[paste("Var_", i, sep="")]]<-i*a[[paste("Col", i, sep="")]]
}
a
#>   year Col1 Col2 Var_1 Var_2
#> 1 2000    1    2     1     4
#> 2 2001    2    4     2     8
#> 3 2002    3    6     3    12
#> 4 2003    4    8     4    16
#> 5 2004    5   10     5    20
#> 6 2005    6   12     6    24
# Tidyverse solution
a %>%
    mutate(Total = select(., Var_1:Var_2) %>% rowSums(na.rm = TRUE))
#>   year Col1 Col2 Var_1 Var_2 Total
#> 1 2000    1    2     1     4     5
#> 2 2001    2    4     2     8    10
#> 3 2002    3    6     3    12    15
#> 4 2003    4    8     4    16    20
#> 5 2004    5   10     5    20    25
#> 6 2005    6   12     6    24    30

Gemaakt op 01-01-2019 door het reprex-pakket(v0.2.1)


Antwoord 2, autoriteit 85%

U kunt colSums(a[,c("Var1", "Var2")])of rowSums(a[,c("Var_1", "Var_2")]). In jouw geval wil je het laatste.


Antwoord 3, autoriteit 3%

Als u met een zeer grote dataset werkt, kan rowsumstraag zijn.

Een alternatief is de functie rowsumsvan de Rfastpakket. Hiervoor moet u uw gegevens tijdens het proces converteren naar een matrixen kolomindexen gebruiken in plaats van namen. Hier is een voorbeeld op basis van uw code:

## load Rfast
library(Rfast)
## create dataset
a <- as.data.frame(c(2000:2005))
a$Col1 <- c(1:6)
a$Col2 <- seq(2,12,2)
colnames(a) <- c("year","Col1","Col2")
for (i in 1:2){
  a[[paste("Var_", i, sep="")]] <- i*a[[paste("Col", i, sep="")]]
}
## get column indices based on names
col_st <- grep("Var_1", colnames(a))  # index of "Var_1" col
col_en <- grep("Var_2", colnames(a))  # index of "Var_2" col
cols   <- c(col_st:col_en)  # indices of all cols from "Var_1" to "Var_2"
## sum rows 4 to 5
a$Total <- rowsums(as.matrix(a[,cols]))

Antwoord 4

met dplyr die je kunt gebruiken

a %>%
rowwise() %>%
mutate(sum = sum(Col1,Col1, na.rm = T))

of efficiënter

a %>%
rowwise() %>%
mutate(sum = sum(across(starts_with("Col")), na.rm = T))

Other episodes