IT

그룹별 변수 합계 방법

itgroup 2023. 7. 7. 18:57
반응형

그룹별 변수 합계 방법

열이 두 개인 데이터 프레임이 있습니다.첫 번째 열에는 "첫 번째", "두 번째", "세 번째"와 같은 범주가 포함되어 있고, 두 번째 열에는 "범주"에서 특정 그룹을 본 횟수를 나타내는 숫자가 포함되어 있습니다.

예:

Category     Frequency
First        10
First        15
First        5
Second       2
Third        14
Third        20
Second       3

데이터를 범주별로 정렬하고 모든 주파수를 합합니다.

Category     Frequency
First        30
Second       5
Third        34

R에서 이걸 어떻게 합니까?

용사를 합니다.aggregate:

aggregate(x$Frequency, by=list(Category=x$Category), FUN=sum)
  Category  x
1    First 30
2   Second  5
3    Third 34

은 위예의에다차다같지수있이다습니정할음과원은중서에 할 수 .list된 여러 은 다을통동데유집여계된메통있수다를 통해 통합될 수.cbind:

aggregate(cbind(x$Frequency, x$Metric2, x$Metric3) ...

댓글 보기), (@latemail ),aggregate.

aggregate(Frequency ~ Category, x, sum)

여러 열을 하려면 또여열집경는우를 할 수 ..가 있음)

aggregate(. ~ Category, x, sum)

또는tapply:

tapply(x$Frequency, x$Category, FUN=sum)
 First Second  Third 
    30      5     34 

이 데이터 사용:

x <- data.frame(Category=factor(c("First", "First", "First", "Second",
                                      "Third", "Third", "Second")), 
                    Frequency=c(10,15,5,2,14,20,3))

또한 dplyr 패키지를 사용할 수도 있습니다.

library(dplyr)
x %>% 
  group_by(Category) %>% 
  summarise(Frequency = sum(Frequency))

#Source: local data frame [3 x 2]
#
#  Category Frequency
#1    First        30
#2   Second         5
#3    Third        34

또는 여러 요약 열의 경우(한 열에서도 작동):

x %>% 
  group_by(Category) %>% 
  summarise(across(everything(), sum))

은 기본 데이터 함수를 몇 가지 입니다.mtcars:

# several summary columns with arbitrary names
mtcars %>% 
  group_by(cyl, gear) %>%                            # multiple group columns
  summarise(max_hp = max(hp), mean_mpg = mean(mpg))  # multiple summary columns

# summarise all columns except grouping columns using "sum" 
mtcars %>% 
  group_by(cyl) %>% 
  summarise(across(everything(), sum))

# summarise all columns except grouping columns using "sum" and "mean"
mtcars %>% 
  group_by(cyl) %>% 
  summarise(across(everything(), list(mean = mean, sum = sum)))

# multiple grouping columns
mtcars %>% 
  group_by(cyl, gear) %>% 
  summarise(across(everything(), list(mean = mean, sum = sum)))

# summarise specific variables, not all
mtcars %>% 
  group_by(cyl, gear) %>% 
  summarise(across(c(qsec, mpg, wt), list(mean = mean, sum = sum)))

# summarise specific variables (numeric columns except grouping columns)
mtcars %>% 
  group_by(gear) %>% 
  summarise(across(where(is.numeric), list(mean = mean, sum = sum)))

다음을 포함한 더 많은 정보를 참조하십시오.%>%연산자, dplyr 소개를 참조하십시오.

rcs에서 제공하는 답변은 작동하고 간단합니다.그러나 대규모 데이터셋을 처리하는 경우 성능 향상이 필요한 경우 보다 신속한 대안이 있습니다.

library(data.table)
data = data.table(Category=c("First","First","First","Second","Third", "Third", "Second"), 
                  Frequency=c(10,15,5,2,14,20,3))
data[, sum(Frequency), by = Category]
#    Category V1
# 1:    First 30
# 2:   Second  5
# 3:    Third 34
system.time(data[, sum(Frequency), by = Category] )
# user    system   elapsed 
# 0.008     0.001     0.009 

위의 data.frame을 사용하여 동일한 것과 비교해 보겠습니다.

data = data.frame(Category=c("First","First","First","Second","Third", "Third", "Second"),
                  Frequency=c(10,15,5,2,14,20,3))
system.time(aggregate(data$Frequency, by=list(Category=data$Category), FUN=sum))
# user    system   elapsed 
# 0.008     0.000     0.015 

열을 유지하려면 다음 구문을 사용합니다.

data[,list(Frequency=sum(Frequency)),by=Category]
#    Category Frequency
# 1:    First        30
# 2:   Second         5
# 3:    Third        34

아래 코드에서 알 수 있듯이 데이터셋이 클수록 차이가 더욱 두드러집니다.

data = data.table(Category=rep(c("First", "Second", "Third"), 100000),
                  Frequency=rnorm(100000))
system.time( data[,sum(Frequency),by=Category] )
# user    system   elapsed 
# 0.055     0.004     0.059 
data = data.frame(Category=rep(c("First", "Second", "Third"), 100000), 
                  Frequency=rnorm(100000))
system.time( aggregate(data$Frequency, by=list(Category=data$Category), FUN=sum) )
# user    system   elapsed 
# 0.287     0.010     0.296 

집계의 에는 집의경다결수있다습니합할음을 조합할 수 .lapply그리고..SD과 같이

data[, lapply(.SD, sum), by = Category]
#    Category Frequency
# 1:    First        30
# 2:   Second         5
# 3:    Third        34

기준() 기능도 사용할 수 있습니다.

x2 <- by(x$Frequency, x$Category, sum)
do.call(rbind,as.list(x2))

이러한 다른 패키지(plyr, reshape)는 data.frame을 반환하는 이점이 있지만 기본 함수이므로 ()에 익숙해질 가치가 있습니다.

년 후, R - 몇 년 후 이 여 에 로 기 유 는 간 을 위 해 기 션 하 추 가 더 하 나 한 xtabs

xtabs(Frequency ~ Category, df)
# Category
# First Second  Third 
#    30      5     34 

아니면 당신이 원한다면,data.frame

as.data.frame(xtabs(Frequency ~ Category, df))
#   Category Freq
# 1    First   30
# 2   Second    5
# 3    Third   34
library(plyr)
ddply(tbl, .(Category), summarise, sum = sum(Frequency))

한다면x데이터가 포함된 데이터 프레임입니다. 그러면 다음과 같이 원하는 작업을 수행할 수 있습니다.

require(reshape)
recast(x, Category ~ ., fun.aggregate=sum)

제가 최근에 개종한 동안에.dplyr의 이러한 작업에 , 분의이유작대업해에형의러한대부,sqldf패키지는 어떤 면에서는 여전히 정말 좋습니다(그리고 IMHO가 더 읽기 쉽습니다).

다음은 이 질문에 어떻게 대답할 수 있는지에 대한 예입니다.sqldf

x <- data.frame(Category=factor(c("First", "First", "First", "Second",
                                  "Third", "Third", "Second")), 
                Frequency=c(10,15,5,2,14,20,3))

sqldf("select 
          Category
          ,sum(Frequency) as Frequency 
       from x 
       group by 
          Category")

##   Category Frequency
## 1    First        30
## 2   Second         5
## 3    Third        34

세 번째 옵션을 추가하려면 다음과 같이 하십시오.

require(doBy)
summaryBy(Frequency~Category, data=yourdataframe, FUN=sum)

편집: 이것은 매우 오래된 대답입니다.이제 사용할 것을 권장합니다.group_by그리고.summarise부터dplyr@docendo 답변에서와 같이.

행렬 또는 데이터 프레임의 그룹별 합계를 반환하는 또 다른 솔루션은 짧고 빠릅니다.

rowsum(x$Frequency, x$Category)

다른 열에 다른 집계 함수를 적용해야 할 때(그리고 기본 R을 고수해야 할 때) 매우 유용하고 효율적입니다.

예.

이 입력을 고려할 때:

DF <-                
data.frame(Categ1=factor(c('A','A','B','B','A','B','A')),
           Categ2=factor(c('X','Y','X','X','X','Y','Y')),
           Samples=c(1,2,4,3,5,6,7),
           Freq=c(10,30,45,55,80,65,50))

> DF
  Categ1 Categ2 Samples Freq
1      A      X       1   10
2      A      Y       2   30
3      B      X       4   45
4      B      X       3   55
5      A      X       5   80
6      B      Y       6   65
7      A      Y       7   50

우리는 그룹을 만들고 싶습니다.Categ1그리고.Categ2그리고 다음의 합을 계산합니다.Samples그리고 평균적인Freq.
다음은 다음을 사용하여 가능한 솔루션입니다.ave:

# create a copy of DF (only the grouping columns)
DF2 <- DF[,c('Categ1','Categ2')]

# add sum of Samples by Categ1,Categ2 to DF2 
# (ave repeats the sum of the group for each row in the same group)
DF2$GroupTotSamples <- ave(DF$Samples,DF2,FUN=sum)

# add mean of Freq by Categ1,Categ2 to DF2 
# (ave repeats the mean of the group for each row in the same group)
DF2$GroupAvgFreq <- ave(DF$Freq,DF2,FUN=mean)

# remove the duplicates (keep only one row for each group)
DF2 <- DF2[!duplicated(DF2),]

결과:

> DF2
  Categ1 Categ2 GroupTotSamples GroupAvgFreq
1      A      X               6           45
2      A      Y               9           40
3      B      X               7           50
6      B      Y               6           65

부터dplyr 1.0.0,그across()사용할 수 있는 기능:

df %>%
 group_by(Category) %>%
 summarise(across(Frequency, sum))

  Category Frequency
  <chr>        <int>
1 First           30
2 Second           5
3 Third           34

여러 변수에 관심이 있는 경우:

df %>%
 group_by(Category) %>%
 summarise(across(c(Frequency, Frequency2), sum))

  Category Frequency Frequency2
  <chr>        <int>      <int>
1 First           30         55
2 Second           5         29
3 Third           34        190

그리고 도우미 선택을 사용하여 변수를 선택합니다.

df %>%
 group_by(Category) %>%
 summarise(across(starts_with("Freq"), sum))

  Category Frequency Frequency2 Frequency3
  <chr>        <int>      <int>      <dbl>
1 First           30         55        110
2 Second           5         29         58
3 Third           34        190        380

표본 데이터:

df <- read.table(text = "Category Frequency Frequency2 Frequency3
                 1    First        10         10         20
                 2    First        15         30         60
                 3    First         5         15         30
                 4   Second         2          8         16
                 5    Third        14         70        140
                 6    Third        20        120        240
                 7   Second         3         21         42",
                 header = TRUE,
                 stringsAsFactors = FALSE)

기능을 사용할 수 있습니다.group.sumRfast 패키지에서.

Category <- Rfast::as_integer(Category,result.sort=FALSE) # convert character to numeric. R's as.numeric produce NAs.
result <- Rfast::group.sum(Frequency,Category)
names(result) <- Rfast::Sort(unique(Category)
# 30 5 34

Rfast는 많은 그룹 기능과group.sum그들 중 하나입니다.

사용.cast대신에recast(참고)'Frequency'지금은'value')

df  <- data.frame(Category = c("First","First","First","Second","Third","Third","Second")
                  , value = c(10,15,5,2,14,20,3))

install.packages("reshape")

result<-cast(df, Category ~ . ,fun.aggregate=sum)

받는 사람:

Category (all)
First     30
Second    5
Third     34
library(tidyverse)

x <- data.frame(Category= c('First', 'First', 'First', 'Second', 'Third', 'Third', 'Second'), 
           Frequency = c(10, 15, 5, 2, 14, 20, 3))

count(x, Category, wt = Frequency)

그룹별로 변수를 합치는 좋은 방법은 다음과 같습니다.

rowsum(numericToBeSummedUp, groups)

기지에서여기만collapse::fsum그리고.Rfast::group.sum더 빨라졌습니다.

속도 및 메모리 소비와 관련하여

collapse::fsum(numericToBeSummedUp, groups)

그룹화된 데이터 프레임을 사용할 때 속도를 높일 수 있는 것이 주어진 예에서 가장 우수했습니다.

GDF <- collapse::fgroup_by(DF, g) #Create a grouped data.frame with group g
#GDF <- collapse::gby(DF, g)      #Alternative

collapse::fsum(GDF)               #Calculate sum per group

이는 데이터 세트가 그룹별로 하위 데이터 세트로 분할된 시점에 근접합니다.

여러 방법에 대한 벤치마크를 통해 단일 열을 요약할 수 있음을 알 수 있습니다.collapse::fsum보다 2배 더 빨랐습니다.Rfast::group.sum보다 7배 더 빠릅니다.rowsum그 뒤를 이었습니다.tapply,data.table,by그리고.dplyr.xtabs그리고.aggregate가장 느립니다.

두 개의 열collapse::fsum다시 가장 빠릅니다. 3배 더 빠릅니다.Rfast::group.sum그보다 5배 더 빠름rowsum그 다음에 다음과 같습니다.data.table,tapply,by그리고.dplyr.다시.xtabs그리고.aggregate가장 느립니다.


벤치마크

set.seed(42)
n <- 1e5
DF <- data.frame(g = as.factor(sample(letters, n, TRUE))
              , x = rnorm(n), y = rnorm(n) )

library(magrittr)

일부 방법에서는 집계 속도를 높이는 데 도움이 될 수 있는 작업을 수행할 수 있습니다.

DT <- data.table::as.data.table(DF)
data.table::setkey(DT, g)

DFG <- collapse::gby(DF, g)
DFG1 <- collapse::gby(DF[c("g", "x")], g)

# Optimized dataset for this aggregation task
# This will also consume time!
DFS <- lapply(split(DF[c("x", "y")], DF["g"]), as.matrix)
DFS1 <- lapply(split(DF["x"], DF["g"]), as.matrix)

열 하나를 요약합니다.

bench::mark(check = FALSE
          , "aggregate" = aggregate(DF$x, DF["g"], sum)
          , "tapply" = tapply(DF$x, DF$g, sum)
          , "dplyr" = DF %>% dplyr::group_by(g) %>% dplyr::summarise(sum = sum(x))
          , "data.table" = data.table::as.data.table(DF)[, sum(x), by = g]
          , "data.table2" = DT[, sum(x), by = g]
          , "by" = by(DF$x, DF$g, sum)
          , "xtabs" = xtabs(x ~ g, DF)
          , "rowsum" = rowsum(DF$x, DF$g)
          , "Rfast" = Rfast::group.sum(DF$x, DF$g)
          , "base Split" = lapply(DFS1, colSums)
          , "base Split Rfast" = lapply(DFS1, Rfast::colsums)
          , "collapse"  = collapse::fsum(DF$x, DF$g)
          , "collapse2"  = collapse::fsum(DFG1)
)
#   expression            min   median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc
#   <bch:expr>       <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl> <int> <dbl>
# 1 aggregate         20.43ms  21.88ms      45.7   16.07MB    59.4     10    13
# 2 tapply             1.24ms   1.39ms     687.     1.53MB    30.1    228    10
# 3 dplyr              3.28ms   4.81ms     209.     2.42MB    13.1     96     6
# 4 data.table         1.59ms   2.47ms     410.     4.69MB    87.7    145    31
# 5 data.table2        1.52ms   1.93ms     514.     2.38MB    40.5    190    15
# 6 by                 2.15ms   2.31ms     396.     2.29MB    26.7    148    10
# 7 xtabs              7.78ms   8.91ms     111.    10.54MB    50.0     31    14
# 8 rowsum           951.36µs   1.07ms     830.     1.15MB    24.1    378    11
# 9 Rfast            431.06µs 434.53µs    2268.     2.74KB     0     1134     0
#10 base Split       213.42µs 219.66µs    4342.       256B    12.4   2105     6
#11 base Split Rfast  76.88µs  81.48µs   10923.    65.05KB    16.7   5232     8
#12 collapse         121.03µs 122.92µs    7965.       256B     2.01  3961     1
#13 collapse2         85.97µs  88.67µs   10749.       256B     4.03  5328     2

두 열을 합

bench::mark(check = FALSE
          , "aggregate" = aggregate(DF[c("x", "y")], DF["g"], sum)
          , "tapply" = list2DF(lapply(DF[c("x", "y")], tapply, list(DF$g), sum))
          , "dplyr" = DF %>% dplyr::group_by(g) %>% dplyr::summarise(x = sum(x), y = sum(y))
          , "data.table" = data.table::as.data.table(DF)[,.(sum(x),sum(y)), by = g]
          , "data.table2" = DT[,.(sum(x),sum(y)), by = g]
          , "by" = lapply(DF[c("x", "y")], by, list(DF$g), sum)
          , "xtabs" = xtabs(cbind(x, y) ~ g, DF)
          , "rowsum" = rowsum(DF[c("x", "y")], DF$g)
          , "Rfast" = list2DF(lapply(DF[c("x", "y")], Rfast::group.sum, DF$g))
          , "base Split" = lapply(DFS, colSums)
          , "base Split Rfast" = lapply(DFS, Rfast::colsums)
          , "collapse" = collapse::fsum(DF[c("x", "y")], DF$g)
          , "collapse2" = collapse::fsum(DFG)
            )
#   expression            min   median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc
#   <bch:expr>       <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl> <int> <dbl>
# 1 aggregate         25.87ms  26.36ms      37.7   20.89MB   132.       4    14
# 2 tapply             2.65ms   3.23ms     312.     3.06MB    22.5     97     7
# 3 dplyr              4.27ms   6.02ms     164.     3.19MB    13.3     74     6
# 4 data.table         2.33ms   3.19ms     309.     4.72MB    57.0    114    21
# 5 data.table2        2.22ms   2.81ms     355.     2.41MB    19.8    161     9
# 6 by                 4.45ms   5.23ms     190.     4.59MB    22.5     59     7
# 7 xtabs             10.71ms  13.14ms      76.1    19.7MB   145.      11    21
# 8 rowsum             1.02ms   1.07ms     850.     1.15MB    23.8    393    11
# 9 Rfast            841.57µs 846.88µs    1150.     5.48KB     0      575     0
#10 base Split       360.24µs 368.28µs    2652.       256B     8.16  1300     4
#11 base Split Rfast 113.95µs 119.81µs    7540.    65.05KB    10.3   3661     5
#12 collapse         201.31µs 204.83µs    4724.       512B     2.01  2350     1
#13 collapse2        156.95µs 161.79µs    5408.       512B     2.02  2683     1

사용할 수 있습니다.rowsum주파수를 계산하는 함수입니다.

data("mtcars")
df <- mtcars
df$cyl <- as.factor(df$cyl)

머리 모양은 다음과 같습니다.

               wt    mpg    cyl
              <dbl> <dbl>   <fct>
Mazda RX4     2.620  21.0   6
Mazda RX4 Wag 2.875  21.0   6
Datsun 710    2.320  22.8   4

그리고나서,

rowsum(df$mpg, df$cyl) #values , group

4   293.3
6   138.2
8   211.4

와 함께dplyr 1.1.0그리고 위에, 당신은 사용할 수 있습니다..bysummarise이 바로 가기는 사용할 수 없습니다.group_by를 반환합니다.ungrouped 데이터 프레임:

library(dplyr)
x %>%  
  summarise(Frequency = sum(Frequency), .by = Category)

언급URL : https://stackoverflow.com/questions/1660124/how-to-sum-a-variable-by-group

반응형