我有以下数据集:
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,点)中的错误:
var1
列的长度必须为1(汇总值),而不是3
出什么问题了?
答案 0 :(得分: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()
答案 1 :(得分:2)
应用此功能时
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))
答案 2 :(得分:1)
这不是最优雅的方法,但是如果您的外部函数只是其他函数的列表,也许您可以只为函数使用一个列表:
myfun_ls <- list(sum,mean,sd)
my2<-dataset%>%
summarise_if(.,is.numeric,.funs=myfun_ls)