`dplyr::summarise` ไม่ยอมรับฟังก์ชันภายนอก

ฉันมีชุดข้อมูลดังต่อไปนี้:

dataset=structure(list(var1 = c(28.5627505742013, 22.8311421908438, 95.2216156944633, 
43.9405107684433, 97.11211245507, 48.4108281508088, 77.1804554760456, 
27.1229329891503, 69.5863061584532, 87.2112890332937), var2 = c(32.9009465128183, 
54.1136392951012, 69.3181485682726, 70.2100433968008, 44.0986660309136, 
62.8759404085577, 79.4413498230278, 97.4315509572625, 62.2505457513034, 
76.0133410431445), var3 = c(89.6971945464611, 67.174579706043, 
37.0924087055027, 87.7977314218879, 29.3221596442163, 37.5143952667713, 
62.6237869635224, 71.3644423149526, 95.3462834469974, 27.4587387405336
), var4 = c(41.5336912125349, 98.2095112837851, 80.7970978319645, 
91.1278881691396, 66.4086666144431, 69.2618868127465, 67.7560870349407, 
71.4932355284691, 21.345994155854, 31.1811877787113), var5 = c(33.9312525652349, 
88.1815139763057, 98.4453701227903, 25.0217059068382, 41.1195872165263, 
37.0983888953924, 66.0217586159706, 23.8814191706479, 40.9594196081161, 
79.7632974945009), var6 = c(39.813664201647, 80.6405956856906, 
30.0273275375366, 34.6203793399036, 96.5195455029607, 44.5830867439508, 
78.7370151281357, 42.010761089623, 23.0079878121614, 58.0372223630548
), kmeans = structure(c(2L, 1L, 3L, 1L, 3L, 1L, 1L, 1L, 2L, 3L
), .Label = c("1", "2", "3"), class = "factor")), .Names = c("var1", 
"var2", "var3", "var4", "var5", "var6", "kmeans"), row.names = c(NA, 
-10L), class = c("tbl_df", "tbl", "data.frame"))

และฟังก์ชั่นต่อไปนี้:

myfun<-function(x){
  c(sum(x),mean(x),sd(x))
}

ด้วย dplyr::summarise เท่านั้น ผลลัพธ์ก็โอเค:

library(tidyverse)

my1<-dataset%>%
  summarise_if(.,is.numeric,.funs=funs(sum,mean,sd))

แต่ด้วย myfun ใช้งานไม่ได้:

my2<-dataset%>%
  summarise_if(.,is.numeric,.funs=funs(myfun))

ข้อผิดพลาดใน summarise_impl(.data, dots) : คอลัมน์ var1 ต้องมีความยาว 1 (ค่าสรุป) ไม่ใช่ 3

มีปัญหาอะไร?


person neves    schedule 12.01.2019    source แหล่งที่มา
comment
คุณช่วยยกตัวอย่างที่แสดง summarise ทำงานได้ไหม ขออภัยในความไม่รู้ เราจะคืนค่าสามค่าในคอลัมน์เดียวได้อย่างไร คุณได้รับข้อผิดพลาดที่แน่นอนคืออะไร?   -  person NelsonGon    schedule 12.01.2019
comment
ปัญหาคือการตั้งค่าหลายค่าให้เป็นคอลัมน์เดียว ฉันไม่รู้ว่ามันใช้เวลานานแค่ไหน แต่คุณสามารถเรียกใช้ฟังก์ชันเหล่านี้แยกกันได้   -  person NelsonGon    schedule 12.01.2019
comment
เพียงตรวจสอบความแตกต่างระหว่าง funs(sum, mean, sd) และ funs(c(sum, mean, sd))   -  person Rich Scriven    schedule 12.01.2019


คำตอบ (3)


คุณสามารถลองใช้วิธีนี้ได้ วิธีการของคุณจะไม่ให้ผลลัพธ์ที่ถูกต้อง เนื่องจากไม่สามารถตัดค่าสองค่าที่ส่งคืนโดยฟังก์ชันที่กำหนดเองของคุณกลับมาในเซลล์เดียว เพื่อหลีกเลี่ยงปัญหา ฉันใช้ enframe กับ list ในฟังก์ชันที่กำหนดเอง:

library(tidyverse)

myfun<-function(x){
    return(list(enframe(c('sum' = sum(x),'mean' = mean(x),'sd' = sd(x)))))
}

ตัวอย่างเช่นกับ mtcars ข้อมูล:

my2<-mtcars%>%
summarise_at(c('mpg','drat'), function(x) myfun(x)) %>% 
unnest() %>% 
select(-name1) %>% 
set_names(nm = c('name', 'mpg', 'drat'))

มันจะให้ผล:

  name        mpg        drat
1  sum 642.900000 115.0900000
2 mean  20.090625   3.5965625
3   sd   6.026948   0.5346787

นอกจากนี้ ยังมีอีกวิธีหนึ่งที่คุณสามารถลองแก้ไขโดยใช้ purrr

ตัวอย่างเช่น:

f <- function(x,...){
    list('mean' = mean(x, ...),'sum' = sum(x, ...))
}

mtcars %>% 
select(mpg, drat) %>% 
map_dfr(~ f(.x, na.rm=T), .id ="Name") %>% 
data.frame()
person PKumar    schedule 12.01.2019

เมื่อคุณใช้ฟังก์ชันนี้

dataset%>% summarise_if(is.numeric,.funs=funs(sum,mean,sd))

คุณกำลังใช้ฟังก์ชันที่แตกต่างกันสามฟังก์ชัน (sum, mean และ sd) ซึ่งใช้กับทุกคอลัมน์ทีละคอลัมน์ ดังนั้นทุกคอลัมน์ที่เป็นตัวเลข ฟังก์ชันเหล่านี้จะถูกนำไปใช้กับมัน ที่นี่เรามีฟังก์ชันที่แตกต่างกันสามฟังก์ชันที่ส่งคืนค่าสามค่า

เกี่ยวกับหน้าที่ของคุณ ฉันคิดว่าสิ่งที่คุณพยายามทำคือ

myfun<-function(x){
  c(sum(x),mean(x),sd(x))
}

ตอนนี้ เมื่อมีการใช้ฟังก์ชันนี้กับคอลัมน์หนึ่ง ฟังก์ชันจะส่งกลับค่าสามค่าให้คุณ ดังนั้นฟังก์ชันหนึ่งจึงส่งคืนค่าสามค่าให้คุณแทน

myfun(dataset$var1)
#[1] 597.17994  59.71799  29.03549

ตามที่ @NelsonGon กล่าวถึงในความคิดเห็น คุณกำลังพยายามเก็บค่าสามค่าไว้ในคอลัมน์เดียว คุณสามารถส่งคืนเป็นรายการตามที่ @Pkumar แสดงหรือรูปแบบของ do บางรูปแบบก็จะช่วยให้คุณบรรลุเป้าหมายได้เช่นกัน หากคุณแยกย่อยฟังก์ชันต่างๆ และแยกฟังก์ชันทั้งสามออกจากกัน ก็จะทำงานในลักษณะเดียวกับที่คุณแสดงไว้ก่อนหน้านี้

myfun1 <- function(x) sum(x)
myfun2  <- function(x) mean(x)
myfun3 <- function(x) sd(x)

dataset %>% summarise_if(is.numeric,.funs=funs(myfun1,myfun2,myfun3))
person Ronak Shah    schedule 12.01.2019

มันไม่ใช่วิธีที่หรูหราที่สุด แต่ถ้าฟังก์ชันภายนอกของคุณเป็นเพียงรายการของฟังก์ชันอื่น ๆ บางทีคุณอาจใช้รายการสำหรับฟังก์ชันของคุณก็ได้:

myfun_ls <- list(sum,mean,sd)
my2<-dataset%>%
  summarise_if(.,is.numeric,.funs=myfun_ls)
person JMueller    schedule 12.01.2019