R 使用data.table计算所有数值列的汇总统计数据(例如平均值)

R 使用data.table计算所有数值列的汇总统计数据(例如平均值),r,data.table,na,R,Data.table,Na,我的数据既有numeric列,也有非numeric列,如下所示: mydt vnum1 vint1 vfac1 vch1 1: -0.30159484 8 3 E 2: -0.09833430 8 1 D 3: -2.15963282 1 3 D 4: 0.03904374 5 2 B 5: 1.54928970 4 1 C 6: -0.7387365

我的数据既有
numeric
列,也有非
numeric
列,如下所示:

mydt
          vnum1 vint1 vfac1 vch1
 1: -0.30159484     8     3    E
 2: -0.09833430     8     1    D
 3: -2.15963282     1     3    D
 4:  0.03904374     5     2    B
 5:  1.54928970     4     1    C
 6: -0.73873654     5     1    A
 7: -0.68594479     9     2    B
 8:  1.35765612     1     2    E
 9:  1.46958351     2     1    B
10: -0.89623979     2     4    E
如何仅选择
数值列
并使用
数据计算其
平均值
。表

我试过这个:

mydt[ , lapply(.SD, mean), ]
#        vnum1 vint1 vfac1 vch1
# 1: -0.046491   4.5    NA   NA
# Warning messages:
# 1: In mean.default(X[[3L]], ...) :
#  argument is not numeric or logical: returning NA
# 2: In mean.default(X[[4L]], ...) :
#  argument is not numeric or logical: returning NA


dput(mydt)
structure(list(vnum1 = c(-0.301594844692861, -0.0983343040483769, 
-2.15963282153076, 0.03904374068617, 1.54928969700272, -0.738736535236348, 
-0.685944791146016, 1.35765612481877, 1.46958350568506, -0.896239790653183
), vint1 = c(8L, 8L, 1L, 5L, 4L, 5L, 9L, 1L, 2L, 2L), vfac1 = structure(c(3L, 
1L, 3L, 2L, 1L, 1L, 2L, 2L, 1L, 4L), .Label = c("1", "2", "3", 
"4"), class = "factor"), vch1 = structure(c(5L, 4L, 4L, 2L, 3L, 
1L, 2L, 5L, 2L, 5L), .Label = c("A", "B", "C", "D", "E"), class = "factor")), .Names = c("vnum1", 
"vint1", "vfac1", "vch1"), class = c("data.table", "data.frame"
), row.names = c(NA, -10L), .internal.selfref = <pointer: 0x991c070>)
根据@Arun的建议,我尝试了以下内容,但无法获得子集:

 xx <- mydt[ , lapply(.SD, is.numeric), ]
 xx
 #    vnum1 vint1 vfac1  vch1
 # 1:  TRUE  TRUE FALSE FALSE

 mydt[ , lapply(.SD, mean), .SDcols = xx]
 # Error in `[.data.table`(mydt, , lapply(.SD, mean), .SDcols = xx) : 
 # .SDcols should be column numbers or names
我缺少数据。帧:

sapply(mydf, is.numeric)
# vnum1 vint1 vfac1  vch1 
#  TRUE  TRUE FALSE FALSE 

mydf[sapply(mydf, is.numeric)]
#         vnum1 vint1
#1  -0.30159484     8
#2  -0.09833430     8
#3  -2.15963282     1
#4   0.03904374     5
#5   1.54928970     4
#6  -0.73873654     5
#7  -0.68594479     9
#8   1.35765612     1
#9   1.46958351     2
#10 -0.89623979     2


sapply(mydf[sapply(mydf, is.numeric)], mean)
#    vnum1     vint1 
#-0.046491  4.500000 
嗯。感谢David的评论,以下作品:

mydt[, sapply(mydt, is.numeric), with = FALSE][,sapply(.SD, mean),]
#    vnum1     vint1 
# -0.046491  4.500000 

mydt[, sapply(mydt, is.numeric), with = FALSE]
#          vnum1 vint1
# 1: -0.30159484     8
# 2: -0.09833430     8
# 3: -2.15963282     1
# 4:  0.03904374     5
# ...

通过在SO上搜索
.SDcols
,我找到了,我认为这很好地解释了如何使用它

cols = sapply(mydt, is.numeric)
cols = names(cols)[cols]
mydt[, lapply(.SD, mean), .SDcols = cols]
#        vnum1 vint1
# 1: -0.046491   4.5
mydt[,sapply(mydt,is.numeric),with=FALSE]
(注意:做这件事的“现代”方法是
mydt[,.SD,.SDcols=is.numeric]
)效率不高,因为它用这些列来子集data.table,这会造成(深度)拷贝—不必要地使用更多内存


并且使用
colMeans
将data.table强制转换为
矩阵
,这同样不是很节省内存。

您可以在一行中使用以下格式,而不必使用
sapply

mydt[,lapply(.SD,mean),.SDcols=is.numeric]

此外,如果您使用的是真实数据,那么您的数据很有可能 价值观以下是在NA的情况下的工作方式:


mydt[,lappy(.SD,函数(i)均值(i,na.rm=T)),.SDcols=is.numeric]
我遇到了同样的问题,下面的代码也可能有帮助

data("mtcars")
mtcars$X1 <- factor(mtcars$gear, levels = c(4,3,5)); str(mtcars) #create an non numeric column X1
my.mean <- function(x){ if(is.numeric(x)) c(mean(x), median(x))} 
my.df <- setNames(as.data.frame(unlist(lapply(mtcars, FUN = my.mean))), "values"); my.df
my.df$names <- rep(c("mean","median"), times = length(row.names(my.df))/2); my.df
my.df$variables <-  rownames(my.df); my.df
library(stringr)
my.df$variables <- str_remove(my.df$variables, "[12]"); my.df 

data_wide <- spread(my.df,  names, values)
data_wide

> data_wide
   variables       mean  median
1         am   0.406250   0.000
2       carb   2.812500   2.000
3        cyl   6.187500   6.000
4       disp 230.721875 196.300
5       drat   3.596563   3.695
6       gear   3.687500   4.000
7         hp 146.687500 123.000
8        mpg  20.090625  19.200
9       qsec  17.848750  17.710
10        vs   0.437500   0.000
11        wt   3.217250   3.325
数据(“mtcars”)

mtcars$X1使用
.SDcols
。有相当多的问题。你应该可以通过搜索一点来到达那里。@Arun,@Davidernburg:请看我上面的编辑。尝试
mydt[,sapply(mydt,is.numeric),with=FALSE]
对于平均值,尝试
mydt[,lapply(.SD[,sapply(.SD.numeric),with=FALSE],mean)]
你也可以通过执行
colMeans(mydt[,sapply)来矢量化整个事情(mydt,is.numeric),带=F])
cols呢
cols = sapply(mydt, is.numeric)
cols = names(cols)[cols]
mydt[, lapply(.SD, mean), .SDcols = cols]
#        vnum1 vint1
# 1: -0.046491   4.5
data("mtcars")
mtcars$X1 <- factor(mtcars$gear, levels = c(4,3,5)); str(mtcars) #create an non numeric column X1
my.mean <- function(x){ if(is.numeric(x)) c(mean(x), median(x))} 
my.df <- setNames(as.data.frame(unlist(lapply(mtcars, FUN = my.mean))), "values"); my.df
my.df$names <- rep(c("mean","median"), times = length(row.names(my.df))/2); my.df
my.df$variables <-  rownames(my.df); my.df
library(stringr)
my.df$variables <- str_remove(my.df$variables, "[12]"); my.df 

data_wide <- spread(my.df,  names, values)
data_wide

> data_wide
   variables       mean  median
1         am   0.406250   0.000
2       carb   2.812500   2.000
3        cyl   6.187500   6.000
4       disp 230.721875 196.300
5       drat   3.596563   3.695
6       gear   3.687500   4.000
7         hp 146.687500 123.000
8        mpg  20.090625  19.200
9       qsec  17.848750  17.710
10        vs   0.437500   0.000
11        wt   3.217250   3.325