จัดกลุ่มตามสองปัจจัยด้วย dplyr

ฉันกำลังดิ้นรนเล็กน้อยกับโครงสร้าง dplyr ใน R ฉันต้องการจัดกลุ่มตามระดับปัจจัยที่แตกต่างกันสองระดับตามลำดับเพื่อให้ได้ผลรวมของตัวแปรอื่น

นี่คือตัวอย่างที่สามารถทำซ้ำได้

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")

และนี่คือความพยายามของฉันจนถึงตอนนี้

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

แต่มันไม่ใช่สิ่งที่ฉันกำลังมองหา ฉันต้องการมีหนึ่งแถวต่อปัจจัย 1 โดยผลลัพธ์จะเป็นดังนี้ (และ 0 ก็คิดเป็นเช่นกัน)

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

ข้อเสนอแนะใด ๆ ?


person ePoQ    schedule 28.05.2021    source แหล่งที่มา


คำตอบ (4)


คุณต้องปรับรูปร่างหรือหมุนข้อมูล เนื่องจากคุณใช้ dplyr อยู่แล้ว คุณจึงสามารถใช้ tidyr::pivot_wider ได้ (หรืออีกทางหนึ่ง reshape2::dcast จะทำงานในลักษณะเดียวกัน แต่จริงๆ แล้วฉันเชื่อว่า pivot_wider มีคุณสมบัติครบถ้วนมากกว่า)

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
ขอบคุณ มันใช้งานได้ดี ยกเว้นการแทนที่ NA ด้วย 0 'ข้อผิดพลาดในvalues_fill[[value]] : subscript out of bounds' - person ePoQ; 28.05.2021
comment
ฉันไม่รู้ มันไม่ได้เกิดขึ้นกับข้อมูลนี้ หากคุณพบว่าคอลัมน์/ค่าใดที่เรียกใช้ โปรดอัปเดตข้อมูลของคุณ แล้วเราจะตรวจสอบ - person r2evans; 28.05.2021
comment
แพ็คเกจที่เป็นระเบียบเรียบร้อยของฉันไม่ทันสมัย ปัญหาได้รับการแก้ไขแล้ว ขอบคุณ - person ePoQ; 31.05.2021

ใช้ 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
การใช้ตัวอย่างที่ทำซ้ำได้และวิธีการแรกที่ฉันได้รับ 'ข้อผิดพลาดในค่าต่างๆ_fn[[ค่า]] : วัตถุประเภท 'บิวท์อิน' ไม่สามารถตั้งค่าย่อยได้' อันที่สองทำงานได้อย่างสมบูรณ์แบบ ขอบคุณ - person ePoQ; 28.05.2021
comment
@ePoQ การใช้ข้อมูลที่คุณแชร์ในคำถามฉันไม่ได้รับข้อผิดพลาดใด ๆ คุณลองรีสตาร์ท R หรือไม่? - person Ronak Shah; 28.05.2021
comment
แพ็คเกจที่เป็นระเบียบเรียบร้อยของฉันไม่ทันสมัย ปัญหาได้รับการแก้ไขแล้ว ขอบคุณ - person ePoQ; 31.05.2021

เราสามารถใช้ xtabs จาก 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

ฉันคิดว่า @akrun's xtabs solution เป็นโซลูชันที่กระชับที่สุดจนถึงตอนนี้ นี่คือตัวเลือก R ฐานอื่นโดยมี aggregate + reshape

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

ให้

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

ตัวเลือก 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 ฮ่าๆ งั้นอย่าเป็นคนแรกดีที่สุด :P - person ThomasIsCoding; 28.05.2021