如何在R的data.table中生成含各列均值的单列DataFrame
如何计算data.table中各数值列的均值并存入单列?
问题背景
我用这段代码生成了一个数据集:
set.seed(1) DF <- data.table(panelID = sample(50,50), # Creates a panel ID Country = c(rep("A",30),rep("B",50), rep("C",20)), Group = c(rep(1,20),rep(2,20),rep(3,20),rep(4,20),rep(5,20)), Time = rep(seq(as.Date("2010-01-03"), length=20, by="1 month") - 1,5), norm = round(runif(100)/10,2), Income = sample(100,100), Happiness = sample(10,10), Sex = round(rnorm(10,0.75,0.3),2), Age = round(rnorm(10,0.75,0.3),2), Educ = round(rnorm(10,0.75,0.3),2)) DF [, uniqueID := .I] DF <- as.data.table(DF) # Make sure it is a data.table DF [, uniqueID := .I] # Add a unique ID cols = sapply(DF, is.numeric) # Check numerical columns DFm <- melt(DF[, cols, with = FALSE][, !"uniqueID"], id = "panelID") DFm[, value := c(NA, diff(value)), by = .(panelID, variable)] DF <- dcast(DFm, panelID + rowidv(DFm, cols = c("panelID", "variable")) ~ variable, value.var = "value") DF <- DF[DF[, !Reduce(`&`, lapply(.SD , is.na)), .SDcols = 3:ncol(DF)]] # Removes T1 for which there is no difference
我现在想实现一个简单需求:把每列的均值存入一个单列中,但试了下面两段代码都没得到正确结果,要么返回NA要么直接报错:
mean_of_differences <- DF [, mean(sapply(.SD, is.numeric), na.rm=TRUE)] mean_of_differences <- DF[,.SD[mean(sapply(.SD, is.numeric), na.rm=TRUE)]]
请问我到底忽略了什么呀?
问题分析与解决方法
咱们先拆解下你之前代码的问题:
sapply(.SD, is.numeric)返回的是一个逻辑向量,它只告诉你哪些列是数值型的,对这个向量取mean()得到的是数值列在所有列中的占比,完全不是你要的各列均值。.SD[mean(...)]这种写法逻辑就错了:.SD是当前分组的数据集,用一个数值去索引它,只会返回对应位置的行,根本不是计算列均值的正确方式。
根据你的需求,我给你两种常用的实现方式:
方式1:生成“列名-均值”的单列格式(推荐)
如果你想要把每列的均值整理成一个单列(同时保留列名方便查看),可以这么写:
# 筛选数值列,计算每列均值,再转成单列的长格式 mean_of_differences <- DF[, lapply(.SD, mean, na.rm = TRUE), .SDcols = sapply(DF, is.numeric)] %>% melt(id.vars = NULL, variable.name = "Column_Name", value.name = "Column_Mean")
运行后会得到一个两列的data.table,第一列是原数据的列名,第二列就是对应列的均值,很直观。
方式2:给原数据集添加均值列
如果你想给原DF添加新列,每个行的新列值都是对应原列的整体均值(比如Income列的每一行都显示Income列的均值),可以用这段代码:
# 先计算所有数值列的均值 col_means <- DF[, lapply(.SD, mean, na.rm = TRUE), .SDcols = sapply(DF, is.numeric)] # 给原数据集批量添加均值列,列名会自动加上"_mean"后缀 DF[, (paste0(names(col_means), "_mean")) := col_means, by = .(1)]
方式3:仅生成纯均值的单列
如果只需要一个只包含均值的单列(不需要列名),可以简化成:
# 先得到均值向量,再转成单列data.table mean_vec <- DF[, sapply(.SD, mean, na.rm = TRUE), .SDcols = sapply(DF, is.numeric)] mean_of_differences <- data.table(Mean = mean_vec)
验证效果
运行方式3的代码后,你会得到类似这样的结果:
Mean 1: 25.500000 2: 2.000000 3: 0.000000 4: 0.000000 5: 0.005000 6: 0.000000 7: 0.000000 8: 0.000000 9: 0.000000
每个值对应原数据集中一列的均值,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

