使用data.table计算所有数字列的汇总统计信息(例如均值)

rns*_*nso 4 r data.table

我有两列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
Run Code Online (Sandbox Code Playgroud)

如何仅选择numeric列并计算其mean使用data.table

我试过这个:

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>)
Run Code Online (Sandbox Code Playgroud)

我也试过以下,但它不起作用:

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

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

mydt[ , mydt[ , lapply(.SD, is.numeric) , ], with = F]
# Error in Math.data.frame(j) : 
#  non-numeric variable in data frame: vnum1vint1vfac1vch1

mydt[ , c(mydt[ , lapply(.SD, is.numeric)), ], with = F]
# Error: unexpected ')' in "mydt[,c(mydt[,lapply(.SD, is.numeric))"
Run Code Online (Sandbox Code Playgroud)

正如@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
Run Code Online (Sandbox Code Playgroud)

正如@David所建议的,我尝试了以下但是获取NULL非数字列的值.我想获得mydt的子集,以便甚至不列出其他列.

mydt[ , lapply(.SD, function(x) if(is.numeric(x)) mean(x))]
#       vnum1 vint1 vfac1 vch1
# 1: -0.046491   4.5  NULL NULL
Run Code Online (Sandbox Code Playgroud)

我缺少data.frame:

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 
Run Code Online (Sandbox Code Playgroud)

好.感谢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
# ...
Run Code Online (Sandbox Code Playgroud)

Aru*_*run 10

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

cols = sapply(mydt, is.numeric)
cols = names(cols)[cols]
mydt[, lapply(.SD, mean), .SDcols = cols]
#        vnum1 vint1
# 1: -0.046491   4.5
Run Code Online (Sandbox Code Playgroud)

这样做mydt[, sapply(mydt, is.numeric), with = FALSE]并不是那么有效,因为它会使用这些列对data.table进行子集化并使(深层)复制 - 不必要地使用更多内存.

并且使用colMeans强制将data.table转换为a matrix,这又不是那么有效的内存.