Kelompokkan berdasarkan dua faktor dengan dplyr

Saya sedikit kesulitan dengan struktur dplyr di R. Saya ingin mengelompokkan secara berurutan berdasarkan dua tingkat faktor yang berbeda untuk mendapatkan jumlah variabel lain.

Berikut adalah contoh yang dapat direproduksi

df <- data.frame(c("A", "A", "A", "B", "C", "C","C"),
                 c("1", "1", "3", "2", "3", "2","2"),
                 c(12, 45, 78, 32, 5, 7, 8))

colnames(df) <- c("factor1","factor2","values")

Dan inilah percobaan saya sejauh ini

test <- df %>%
  group_by(factor1, factor2) %>%
  summarise(sum(values))

# A tibble: 5 x 3
# Groups:   factor1 [3]
factor1 factor2 `sum(values)`
<fct>   <fct>           <dbl>
1 A       1                  57
2 A       3                  78
3 B       2                  32
4 C       2                  15
5 C       3                   5

Tapi bukan itu yang saya cari. Saya ingin memiliki satu baris per faktor 1, dengan hasil seperti ini (dan 0 juga diperhitungkan)

        1   2   3 
A       57  0   78           
B       0   32  0             
C       0   15  5    

ada saran?


person ePoQ    schedule 28.05.2021    source sumber


Jawaban (4)


Anda perlu membentuk ulang atau memutar data. Karena Anda sudah menggunakan dplyr, Anda dapat menggunakan tidyr::pivot_wider. (Atau, reshape2::dcast akan bekerja dengan cara yang sama, meskipun sejujurnya saya yakin pivot_wider lebih berfitur lengkap.)

library(dplyr)
test <- df %>%
  group_by(factor1, factor2) %>%
  summarise(z = sum(values))
tidyr::pivot_wider(test, factor1, names_from = "factor2", values_from = "z",
                   values_fill = 0)
# # A tibble: 3 x 4
# # Groups:   factor1 [3]
#   factor1   `1`   `3`   `2`
#   <chr>   <dbl> <dbl> <dbl>
# 1 A          57    78     0
# 2 B           0     0    32
# 3 C           0     5    15
person r2evans    schedule 28.05.2021
comment
Terima kasih, ini berfungsi dengan baik, kecuali untuk mengganti NA dengan 0. 'Kesalahan dalam nilai_isi[[nilai]] : subskrip di luar batas' - person ePoQ; 28.05.2021
comment
Saya tidak tahu, itu tidak terjadi dengan data ini. Jika Anda dapat menemukan kolom/nilai apa yang memicunya, perbarui data Anda dan saya akan memeriksanya. - person r2evans; 28.05.2021
comment
Paket rapi saya tidak mutakhir. Masalah terselesaikan, terima kasih. - person ePoQ; 31.05.2021

Menggunakan pivot_Wider -

tidyr::pivot_wider(df, names_from = factor2, values_from = values, 
                    values_fn  =sum, values_fill = 0)

#  factor1   `1`   `3`   `2`
#  <chr>   <dbl> <dbl> <dbl>
#1 A          57    78     0
#2 B           0     0    32
#3 C           0     5    15

Or in data.table -

library(data.table)
dcast(setDT(df),factor1~factor2, value.var = 'values', fun.aggregate = sum)
person Ronak Shah    schedule 28.05.2021
comment
Menggunakan contoh yang dapat direproduksi dan metode pertama saya mendapatkan 'Kesalahan dalam nilai_fn[[nilai]] : objek bertipe 'bawaan' tidak dapat disubset'. Yang kedua berfungsi dengan baik, terima kasih - person ePoQ; 28.05.2021
comment
@ePoQ Menggunakan data yang Anda bagikan dalam pertanyaan saya tidak mendapatkan kesalahan apa pun. Apakah Anda mencoba me-restart R? - person Ronak Shah; 28.05.2021
comment
Paket rapi saya tidak mutakhir. Masalah terselesaikan, terima kasih. - person ePoQ; 31.05.2021

Kita dapat menggunakan xtabs dari base R

xtabs(values ~ factor1 + factor2 , df)
#       factor2
#factor1  1  2  3
#      A 57  0 78
#      B  0 32  0
#      C  0 15  5
person akrun    schedule 28.05.2021

Menurut saya solusi xtabs@akrun adalah solusi paling ringkas sejauh ini. Ini adalah opsi basis R lainnya, dengan aggregate + reshape

reshape(
  aggregate(values ~ ., df, sum),
  direction = "wide",
  idvar = "factor1",
  timevar = "factor2",
)

memberi

  factor1 values.1 values.2 values.3
1       A       57       NA       78
2       B       NA       32       NA
3       C       NA       15        5

Opsi data.table

> dcast(setDT(df), factor1 ~ factor2, sum)
Using 'values' as value column. Use 'value.var' to override
   factor1  1  2  3
1:       A 57  0 78
2:       B  0 32  0
3:       C  0 15  5
person ThomasIsCoding    schedule 28.05.2021
comment
@akrun Haha, kalau begitu, jangan jadi yang pertama itu yang terbaik :P - person ThomasIsCoding; 28.05.2021