R按数据表列列出的汇总统计数据
我想为一个包含50多列的数据表创建一个数据字典。首先,我想创建summary对象、数据表或类似对象,在源数据表中每列有一行,列显示最早和最新的非缺失值、最小值和最大值、缺失值的数量等。我试图通过循环源数据表的列来实现这一点,但我无法让计算正常进行。下面是我的代码的简化版本,加上一段代码,可以实现我想要的功能,但没有循环:R按数据表列列出的汇总统计数据,r,loops,datatable,R,Loops,Datatable,我想为一个包含50多列的数据表创建一个数据字典。首先,我想创建summary对象、数据表或类似对象,在源数据表中每列有一行,列显示最早和最新的非缺失值、最小值和最大值、缺失值的数量等。我试图通过循环源数据表的列来实现这一点,但我无法让计算正常进行。下面是我的代码的简化版本,加上一段代码,可以实现我想要的功能,但没有循环: require("data.table") dtTest <- data.table(dObsDt = c("2020-08-01&quo
require("data.table")
dtTest <- data.table(dObsDt = c("2020-08-01","2020-08-02","2020-08-03")
, nPrcp.LAKE = c(NA,12,13)
, nPrcp.PLAT = c(NA,NA,33)
)
dtTest
# Using loop
# Runs without error but does not produce desired results
vsCols <- colnames(dtTest)
dtColDesc <- data.table()
for (lasCol in vsCols) {
ldtVar <- data.table()
ladEarliest <- dtTest[!is.na(eval(lasCol)),list(dLatest=min(dObsDt))][[1]]
lanMax <- dtTest[!is.na(eval(lasCol)),list(dMax=max(eval(lasCol)))][[1]]
ldtVar[,':=' (sColName = lasCol
, nMax = lanMax
, dEarliest = ladEarliest
)]
dtColDesc <- rbind(dtColDesc, ldtVar, fill=TRUE)
}
dtColDesc
# Remove loop
# Runs without error and produces desired results but not scalable
vsCols <- colnames(dtTest)
dtColDesc <- data.table()
ldtVar <- data.table()
ladEarliest <- dtTest[!is.na(dObsDt),list(dLatest=min(dObsDt))][[1]]
lanMax <- dtTest[!is.na(dObsDt),list(dMax=max(dObsDt))][[1]]
ldtVar[,':=' (sColName = lasCol
, nMax = lanMax
, dEarliest = ladEarliest
)]
dtColDesc <- rbind(dtColDesc, ldtVar, fill=TRUE)
ldtVar <- data.table()
ladEarliest <- dtTest[!is.na(nPrcp.LAKE),list(dLatest=min(dObsDt))][[1]]
lanMax <- dtTest[!is.na(nPrcp.LAKE),list(dMax=max(nPrcp.LAKE))][[1]]
ldtVar[,':=' (sColName = lasCol
, nMax = lanMax
, dEarliest = ladEarliest
)]
dtColDesc <- rbind(dtColDesc, ldtVar, fill=TRUE)
ldtVar <- data.table()
ladEarliest <- dtTest[!is.na(nPrcp.PLAT),list(dLatest=min(dObsDt))][[1]]
lanMax <- dtTest[!is.na(nPrcp.PLAT),list(dMax=max(nPrcp.PLAT))][[1]]
ldtVar[,':=' (sColName = lasCol
, nMax = lanMax
, dEarliest = ladEarliest
)]
dtColDesc <- rbind(dtColDesc, ldtVar, fill=TRUE)
dtColDesc
require(“data.table”)
dtTest您可以通过以下方式大致实现您想要的功能:
data.table(sColName = colnames(dtTest),
max = sapply(dtTest, max, na.rm=T),
min = sapply(dtTest, min, na.rm=T),
median = sapply(dtTest, median, na.rm=T),
nmissing = sapply(dtTest, function(x) sum(is.na(x)))
)
但是,请注意,每列中都会有多个数据类型,这意味着大多数列最终都会以字符形式存储数字和日期。如果只是为了快速总结,这不是什么大问题,但是如果您想将此数据传递到其他内容上,则会出现问题。对于数据帧中最早和最新的非缺失值以外的信息,请参见descripe()psych
包中的
函数生成一个表,其中输入数据框中的列以行表示,各种描述性统计数据以列表示。我们用mtcars
数据框说明:
library(psych)
describe(mtcars)
> describe(mtcars)
vars n mean sd median trimmed mad min max range skew
mpg 1 32 20.09 6.03 19.20 19.70 5.41 10.40 33.90 23.50 0.61
cyl 2 32 6.19 1.79 6.00 6.23 2.97 4.00 8.00 4.00 -0.17
disp 3 32 230.72 123.94 196.30 222.52 140.48 71.10 472.00 400.90 0.38
hp 4 32 146.69 68.56 123.00 141.19 77.10 52.00 335.00 283.00 0.73
drat 5 32 3.60 0.53 3.70 3.58 0.70 2.76 4.93 2.17 0.27
wt 6 32 3.22 0.98 3.33 3.15 0.77 1.51 5.42 3.91 0.42
qsec 7 32 17.85 1.79 17.71 17.83 1.42 14.50 22.90 8.40 0.37
vs 8 32 0.44 0.50 0.00 0.42 0.00 0.00 1.00 1.00 0.24
am 9 32 0.41 0.50 0.00 0.38 0.00 0.00 1.00 1.00 0.36
gear 10 32 3.69 0.74 4.00 3.62 1.48 3.00 5.00 2.00 0.53
carb 11 32 2.81 1.62 2.00 2.65 1.48 1.00 8.00 7.00 1.05
kurtosis se
mpg -0.37 1.07
cyl -1.76 0.32
disp -1.21 21.91
hp -0.14 12.12
drat -0.71 0.09
wt -0.02 0.17
qsec 0.34 0.32
vs -2.00 0.09
am -1.92 0.09
gear -1.07 0.13
carb 1.26 0.29
>
最早和最新的非缺失值可以通过另一个答案中提到的sapply()
和pastecs::first()
或pastecs::last()
的组合添加。当我们在这些函数上设置参数na.rm=TRUE
时,它们会检索第一个(或最后一个)不丢失的值
summaryDf <- describe(mtcars)
library(pastecs)
summaryDf$earliest <- sapply(mtcars, function(x) { first(x,na.rm=TRUE)})
summaryDf$latest <- sapply(mtcars, function(x) {last(x,na.rm=TRUE)})
我们可以通过将数据帧的第一行和最后一行设置为NA
,然后重新运行计算来验证非缺失值的行为
mtcars[c(1,32),] <- NA
summaryDf$earliest = sapply(mtcars, function(x){ first(x,na.rm=TRUE) })
summaryDf$latest <- sapply(mtcars, function(x) {last(x,na.rm=TRUE)})
summaryDf
mtcars[c(2,31),]
对于单列统计数据,其他两种建议的解决方案都能很好地工作。对于两列统计数据,这可能不是最优雅的解决方案,但它可以工作:
vsCols <- colnames(dtTest)
dtColDesc <- data.table()
for (lasCol in vsCols) {
ldtVar <- data.table()
ladEarliest <- dtTest[!is.na(dtTest[[lasCol]]),list(dEarliest=min(dObsDt))][[1]]
ladLatest <- dtTest[!is.na(dtTest[[lasCol]]),list(dLatest=max(dObsDt))][[1]]
ldtVar[,':=' (sColName = lasCol
, dEarliest = ladEarliest
, dLatest = ladLatest
)]
dtColDesc <- rbind(dtColDesc, ldtVar, fill=TRUE)
}
dtColDesc
vsCols谢谢。这让我了解了大部分情况,但我需要为每个变量找到最早(min dObsDt)和最新(max dObsDt)的非缺失值,我不知道这种方法可以做到这一点。我遗漏了什么吗?我的回答只是一般方法的一个例子:-)您可以为您可能想要执行的任何其他操作添加行。例如earliest=sappy(dtTest,函数(x){first(x[!is.na(x)])}
据我所知,sapply应用于数据表时的工作方式是,它将每列作为向量提取出来,并允许我进行计算,这为我提供了所需的大多数描述性统计数据,但我认为它不允许我进行最早和最新的计算。对于这些值,我需要在两列上进行计算:找到最小值um和一列的最大值dObsDt,用于具有另一列的非缺失值的所有行,在本例中为nPrcp.PLAT,并对50+列中的每一列执行该操作。sapply将处理得很好:您可以使用它向函数发送其他静态参数。因此,如果您扩展函数以获取第二列(日期)然后,您可以始终将该列作为第二个函数参数传递。例如,earlime=sappy(dtTest,function(x){…},dtTest$MyDateCol)
我感谢您的帮助,但我无法让它工作。我尝试了我能想到的逗号、圆括号和花括号的所有组合,但我无法让sappy同时使用“循环”列和日期列。你有没有可能给我指一个能详细说明这一点的资源?
> summaryDf
vars n mean sd median trimmed mad min max range skew
mpg 1 32 20.09 6.03 19.20 19.70 5.41 10.40 33.90 23.50 0.61
cyl 2 32 6.19 1.79 6.00 6.23 2.97 4.00 8.00 4.00 -0.17
disp 3 32 230.72 123.94 196.30 222.52 140.48 71.10 472.00 400.90 0.38
hp 4 32 146.69 68.56 123.00 141.19 77.10 52.00 335.00 283.00 0.73
drat 5 32 3.60 0.53 3.70 3.58 0.70 2.76 4.93 2.17 0.27
wt 6 32 3.22 0.98 3.33 3.15 0.77 1.51 5.42 3.91 0.42
qsec 7 32 17.85 1.79 17.71 17.83 1.42 14.50 22.90 8.40 0.37
vs 8 32 0.44 0.50 0.00 0.42 0.00 0.00 1.00 1.00 0.24
am 9 32 0.41 0.50 0.00 0.38 0.00 0.00 1.00 1.00 0.36
gear 10 32 3.69 0.74 4.00 3.62 1.48 3.00 5.00 2.00 0.53
carb 11 32 2.81 1.62 2.00 2.65 1.48 1.00 8.00 7.00 1.05
kurtosis se earliest latest
mpg -0.37 1.07 21.00 15.00
cyl -1.76 0.32 6.00 8.00
disp -1.21 21.91 160.00 301.00
hp -0.14 12.12 110.00 335.00
drat -0.71 0.09 3.90 3.54
wt -0.02 0.17 2.88 3.57
qsec 0.34 0.32 17.02 14.60
vs -2.00 0.09 0.00 0.00
am -1.92 0.09 1.00 1.00
gear -1.07 0.13 4.00 5.00
carb 1.26 0.29 4.00 8.00
> mtcars[c(2,31),]
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 Wag 21 6 160 110 3.90 2.875 17.02 0 1 4 4
Maserati Bora 15 8 301 335 3.54 3.570 14.60 0 1 5 8
vsCols <- colnames(dtTest)
dtColDesc <- data.table()
for (lasCol in vsCols) {
ldtVar <- data.table()
ladEarliest <- dtTest[!is.na(dtTest[[lasCol]]),list(dEarliest=min(dObsDt))][[1]]
ladLatest <- dtTest[!is.na(dtTest[[lasCol]]),list(dLatest=max(dObsDt))][[1]]
ldtVar[,':=' (sColName = lasCol
, dEarliest = ladEarliest
, dLatest = ladLatest
)]
dtColDesc <- rbind(dtColDesc, ldtVar, fill=TRUE)
}
dtColDesc