dplyr을 사용하여 여러 열의 합계


98

내 질문에는 데이터 프레임의 여러 열에 걸쳐 값을 합산하고을 사용 하여이 합계에 해당하는 새 열을 만드는 것이 포함됩니다 dplyr. 열의 데이터 항목은 binary (0,1)입니다. 의 summarise_each또는 mutate_each함수의 행 방식 아날로그를 생각하고 dplyr있습니다. 다음은 데이터 프레임의 최소 예입니다.

library(dplyr)
df=data.frame(
  x1=c(1,0,0,NA,0,1,1,NA,0,1),
  x2=c(1,1,NA,1,1,0,NA,NA,0,1),
  x3=c(0,1,0,1,1,0,NA,NA,0,1),
  x4=c(1,0,NA,1,0,0,NA,0,0,1),
  x5=c(1,1,NA,1,1,1,NA,1,0,1))

> df
   x1 x2 x3 x4 x5
1   1  1  0  1  1
2   0  1  1  0  1
3   0 NA  0 NA NA
4  NA  1  1  1  1
5   0  1  1  0  1
6   1  0  0  0  1
7   1 NA NA NA NA
8  NA NA NA  0  1
9   0  0  0  0  0
10  1  1  1  1  1

다음과 같이 사용할 수 있습니다.

df <- df %>% mutate(sumrow= x1 + x2 + x3 + x4 + x5)

그러나 이것은 각 열의 이름을 작성하는 것을 포함합니다. 50 개의 열이 있습니다. 또한이 작업을 구현하려는 루프의 다른 반복에서 열 이름이 변경되므로 열 이름을 제공하지 않으려 고합니다.

어떻게 가장 효율적으로 할 수 있습니까? 도움을 주시면 대단히 감사하겠습니다.


11
dplyr? 왜 df$sumrow <- rowSums(df, na.rm = TRUE)기본 R에서 단순하지 않습니까? 또는 df$sumrow <- Reduce(`+`, df)당신은 당신이했던 정확한 일을 복제 할 경우 dplyr.
데이비드 Arenburg

7
당신과 모두를 할 수 dplyr처럼 너무 df %>% mutate(sumrow = Reduce(`+`, .))df %>% mutate(sumrow = rowSums(.))
데이비드 Arenburg

2
최신 dplyr버전으로 업데이트 하면 작동합니다.
데이비드 Arenburg

1
David Arenburg의 제안은 패키지 dplyr @DavidArenburg를 업데이트 한 후 작동했습니다
amo

1
@boern David Arenburgs 의견은 최고의 답변이자 가장 직접적인 솔루션이었습니다. 귀하의 대답은 작동하지만 일부 경우에는 적합하지 않을 수있는 NA 값을 0으로 바꾸는 추가 단계가 포함됩니다.
amo

답변:


112

어때

각 열을 요약

df %>%
   replace(is.na(.), 0) %>%
   summarise_all(funs(sum))

각 행을 요약

df %>%
   replace(is.na(.), 0) %>%
   mutate(sum = rowSums(.[1:5]))

8
summarise_each필요한 것은 각 행을 따라 합계하는 동안 각 열을 따라 요약합니다
amo

1
나는 똑같은 것을 달성하려고 노력하고 있지만 내 DF에는 문자 인 열이 있으므로 모든 열을 합할 수는 없습니다. (.[1:5])부품을 수정해야 할 것 같지만, 불행히도 구문에 익숙하지 않거나 도움말을 찾는 방법을 모릅니다. 시도 mutate(sum = rowSums(is.numeric(.)))했지만 작동하지 않았습니다.
ccamara

5
내가 참조. 당신은 제공 할 수 있습니다 df %>% replace(is.na(.), 0) %>% select_if(is.numeric) %>% summarise_each(funs(sum))슛을?
Boern

2
더 이상 사용되지 않는 summarise_all대신 대신 사용하십시오 summarise_each.
hmhensen

2
mutate(sum = rowSums(.[,-1]))처리해야 할 열 수를 모르는 경우 구문 이 유용 할 수 있습니다.
Paulo S. Abreu

32

특정 열만 합산하려면 다음과 같이 사용합니다.

library(dplyr)
df=data.frame(
  x1=c(1,0,0,NA,0,1,1,NA,0,1),
  x2=c(1,1,NA,1,1,0,NA,NA,0,1),
  x3=c(0,1,0,1,1,0,NA,NA,0,1),
  x4=c(1,0,NA,1,0,0,NA,0,0,1),
  x5=c(1,1,NA,1,1,1,NA,1,0,1))
df %>% select(x3:x5) %>% rowSums(na.rm=TRUE) -> df$x3x5.total
head(df)

이렇게하면 dplyr::select의 구문을 사용할 수 있습니다 .


다른 이상이 방법처럼 나는이 0의 NA를 강요 필요로하지 않기 때문에
마이클 벨 하우스에게

그리고 더 나은 그렙보다 쉽게하기 때문에 X4 같은 것들을 처리하기 : X11
도브 로젠버그

32

특정 패턴 이름을 가진 변수를 합산하기 위해 정규식 일치를 사용합니다. 예를 들면 :

df <- df %>% mutate(sum1 = rowSums(.[grep("x[3-5]", names(.))], na.rm = TRUE),
                    sum_all = rowSums(.[grep("x", names(.))], na.rm = TRUE))

이렇게하면 데이터 프레임의 특정 변수 그룹의 합계로 둘 이상의 변수를 만들 수 있습니다.


훌륭한 솔루션! 최근 릴리스에서이 작업을 수행하는 특정 dplyr 함수를 찾고 있었지만 찾을 수 없었습니다
agenis

이 솔루션은 훌륭합니다. 포함하지 않으려는 열이있는 경우 특정 패턴과 일치하는 열을 선택하도록 grep () 문을 디자인하기 만하면됩니다.
Trenton Hoffman

1
@TrentonHoffman은 특정 패턴의 열을 선택 취소하는 비트입니다. 단지 필요한 -기호 :rowSums(.[-grep("x[3-5]", names(.))], na.rm = TRUE)
alexb523

22

이 문제가 자주 발생하며 가장 쉬운 방법 apply()mutate명령 내 에서 함수 를 사용하는 것 입니다.

library(tidyverse)
df=data.frame(
  x1=c(1,0,0,NA,0,1,1,NA,0,1),
  x2=c(1,1,NA,1,1,0,NA,NA,0,1),
  x3=c(0,1,0,1,1,0,NA,NA,0,1),
  x4=c(1,0,NA,1,0,0,NA,0,0,1),
  x5=c(1,1,NA,1,1,1,NA,1,0,1))

df %>%
  mutate(sum = select(., x1:x5) %>% apply(1, sum, na.rm=TRUE))

여기서 표준 dplyr트릭 (예 : starts_with()또는 contains())을 사용하여 열을 선택하려는 모든 것을 사용할 수 있습니다 . 단일 mutate명령 내에서 모든 작업을 수행함으로써이 조치는 dplyr처리 단계 스트림 내의 어느 곳에서나 발생할 수 있습니다 . 마지막으로, apply()함수를 사용하면 목적에 맞게 구축 된 요약 기능을 포함하여 필요한 요약을 유연하게 사용할 수 있습니다.

또는 tidyverse가 아닌 함수를 사용하는 아이디어가 매력적이지 않다면 열을 모아서 요약 한 다음 결과를 다시 원래 데이터 프레임에 조인 할 수 있습니다.

df <- df %>% mutate( id = 1:n() )   # Need some ID column for this to work

df <- df %>%
  group_by(id) %>%
  gather('Key', 'value', starts_with('x')) %>%
  summarise( Key.Sum = sum(value) ) %>%
  left_join( df, . )

여기서는 starts_with()함수를 사용하여 열을 선택하고 합계를 계산했으며 NA값으로 원하는 모든 작업을 수행 할 수 있습니다 . 이 접근 방식의 단점은 매우 유연하지만 dplyr데이터 정리 단계 의 흐름에 적합하지 않다는 것 입니다.


3
apply이것이 rowSums설계된 것일 때 사용하는 것은 어리석은 것 같습니다 .
zacdav

6
이 경우 rowSums는 정말 잘 작동 rowMeans하지만 "계산해야하는 것이 합계 나 평균이 아니면 어떨까요?"에 대해 항상 조금 이상하게 생각했습니다. 그러나 99 %의 경우 이와 같은 작업을 수행해야합니다. 합계 또는 평균이므로 일반 apply기능 을 사용할 때 추가 유연성이 보장 되지 않을 수 있습니다.
Derek Sonderegger

22

reduce()from을 사용하면 모든 행에 대한 반복을 피하고 벡터화 된 작업을 활용하기 때문에 purrr보다 약간 빠르며 rowSums확실히 빠릅니다 apply.

library(purrr)
library(dplyr)
iris %>% mutate(Petal = reduce(select(., starts_with("Petal")), `+`))

참조 타이밍에 대한


나는 이것을 좋아하지만 필요할 때 어떻게 할 것인가na.rm = TRUE
see24

@ see24 무슨 말인지 잘 모르겠습니다. 이것은 길이가 모두 같은 벡터 a + b + c를 더합니다. 각 벡터는 서로 다른 위치에 NA가있을 수도 있고 없을 수도 있으므로 무시할 수 없습니다. 이렇게하면 벡터가 정렬되지 않습니다. NA 값을 제거하려면 나중에 제거해야합니다. 예를 들어 drop_na
skd

rowSums(select(., matches("myregex")) , na.rm = TRUE))NA를 무시하는 데 필요한 것이기 때문에 결국 그렇게했습니다 . 그래서 숫자가 sum(NA, 5)결과라면 5입니다. 그러나 당신은 감소가 더 낫다고 말 rowSums했으므로이 상황에서 그것을 사용할 방법이 있는지 궁금합니다.
see24

내가 참조. 합계를 원하고 NA 값을 확실히 무시하려면 rowSums버전이 가장 좋습니다. 가장 큰 단점은이다 rowSumsrowMeans(이가 두드러 느린 감소보다,하지만 훨씬 의해) 사용할 수 있습니다. 합계가 아닌 다른 작업을 수행해야하는 경우 reduce버전이 유일한 옵션 일 수 있습니다. apply이 경우 사용하지 마십시오 .
skd

1

의 최신 버전에서는 with 를 사용하여 특정 행 단위 변형이없는 함수에 대해 행 단위 집계를 수행 dplyr할 수 있지만 행 단위 변형이있는 경우 더 빠릅니다.rowwise()c_across

이후 rowwise()그룹화의 단지 특별한 형태이며에 동사는 가능성이 파이프를 원하는 것이다 작업 방식을 변경 ungroup()하여 행 방향으로 작업을 수행 한 후.

행 범위를 선택하려면 :

df %>%
  dplyr::rowwise() %>% 
  dplyr::mutate(sumrange = sum(dplyr::c_across(x1:x5), na.rm = T))
# %>% dplyr::ungroup() # you'll likely want to ungroup after using rowwise()

유형별로 행을 선택하려면 :

df %>%
  dplyr::rowwise() %>% 
  dplyr::mutate(sumnumeric = sum(c_across(where(is.numeric)), na.rm = T))
# %>% dplyr::ungroup() # you'll likely want to ungroup after using rowwise()

특정 경우에 행 방식 변형이 있으므로 다음을 수행 할 수 있습니다 ( across대신 사용에 유의하십시오 ).

df %>%
  dplyr::mutate(sumrow = rowSums(dplyr::across(x1:x5), na.rm = T))
# %>% dplyr::ungroup() # you'll likely want to ungroup after using rowwise()

자세한 내용은 rowwise 페이지를 참조하세요 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.