如何在数据表列中进行循环?
Posted
技术标签:
【中文标题】如何在数据表列中进行循环?【英文标题】:How can I do a loop in data table columns? 【发布时间】:2022-01-18 16:14:51 【问题描述】:我知道如何函数和循环,我想将它们与数据表对象结合起来,目的是进行探索性数据分析。
我做了这个函数:
aed <- function(x)
mean <- mean(x, na.rm=TRUE)
desvtip <- sd(x, na.rm=TRUE)
qss <- quantile(x, probs=c(0, 0.01, 0.05, 0.25, 0.50, 0.75, 0.95, 0.99, 1), na.rm=TRUE)
names(qss) <- NULL
min <- qss[1]
p1 <- qss[2]
p5 <- qss[3]
p25 <- qss[4]
median <- qss[5]
p75 <- qss[6]
p95 <- qss[7]
p99 <- qss[8]
max <- qss[9]
ric <- p75-p25
return( c(mean=mean, st=desvtip, min=min, p1=p1, p5=p5, p25=p25, p50=median,
p75=p75, p95=p95,p99=p99, max=max,rangic=ric))
我有一个这样的数据表(称为 Master):
V1 | V2 | V3 | V4 |
---|---|---|---|
532.215 | float_value | float_value | float_value |
123.258 | float_value | float_value | float_value |
0.025 | float_value | float_value | float_value |
每一列都是浮点型。
所以,我想用一个循环来处理我的函数的每一列,并制作一个像这样的表格结果:
Column_Name | Mean | st | Min | Max | ... |
---|---|---|---|---|---|
V1 | mean of V1 | st of V1 | ... | ... | ... |
V2 | mean of V2 | st of V2 | ... | ... | ... |
V3 | mean of V3 | st of V3 | ... | ... | ... |
V4 | mean of V4 | st of V4 | ... | ... | ... |
我试过这样循环。
results <- NULL
for(i in 1:ncol(Master)) # for-loop over columns
col_name <- colnames(Master)[i] #select column name
analysis <- aed(Master[,paste0(colnames(Master)[i])]) #use my function
r_row <- cbind(col_name, analysis) #combine column name and resuts of aed in a row
results <- rbind(results, r_row) # combine every row in a table
我不明白的部分是为什么 Master[,paste0(colnames(Master)[i])]
when i = 1 与 Master[,"V1"]
不一样。
控制台返回:
> Master[,paste0(colnames(Master)[i])] # when i =1
[1] "V1"
> Master[,"V1"]
V1
1: 0
2: 2
3: 2
4: 0
5: 0
6: 0
有人可以帮帮我吗?如果您有更好的想法,则无需使用我的循环,但如果有人可以解释为什么 Master[,paste0(colnames(Master)[i])]
不起作用,我会非常感激。
【问题讨论】:
仅供参考,标签推荐系统不完善。在发布您的问题之前,请检查建议的标签。在这种情况下,您有 datatable 模棱两可,但在其描述中明确表示 “对于 data.table R 包,请使用 data.table”; rstudio 标记也仅用于有关 IDE 的问题,其描述为 “请勿将此标记用于一般 R 编程问题”。 【参考方案1】:不需要for
循环。事实上,将rbind
数据迭代到表格工作总线效率非常低,并且扩展性极差,请参阅R Inferno 第 2 章,增长对象。
这是您的 aed
函数的改编版:
aed <- function(nm, x, na.rm = FALSE)
percentiles <- c(0, 1, 5, 25, 50, 75, 95, 99, 100)
qss <- setNames(quantile(x, percentiles/100, na.rm = na.rm), paste0("p", percentiles))
names(qss)[c(1,5,9)] <- c("min", "median", "max")
vals <- c(mean = mean(x, na.rm = na.rm), st = sd(x, na.rm = na.rm), qss, rangeic = qss["p75"] - qss["p25"])
m <- matrix(vals, nrow = 1, dimnames = list(NULL, names(vals)))
cbind(data.table(Column_Name = nm), m)
一些示例数据,我不知道它是否与您使用的匹配。
library(data.table)
set.seed(42)
dat <- data.table(V1 = runif(1000), V2 = runif(1000))
dat
# V1 V2
# <num> <num>
# 1: 0.914806043 0.84829322
# 2: 0.937075413 0.06274633
# 3: 0.286139535 0.81984509
# 4: 0.830447626 0.53936029
# 5: 0.641745519 0.49902010
# 6: 0.519095949 0.02222732
# 7: 0.736588315 0.55409313
# 8: 0.134666597 0.71989760
# 9: 0.656992290 0.23571523
# 10: 0.705064784 0.81187968
# ---
# 991: 0.750519822 0.72004398
# 992: 0.097692942 0.98333927
# 993: 0.815567016 0.16192736
# 994: 0.858393029 0.76617988
# 995: 0.117157300 0.95396922
# 996: 0.137397162 0.26590719
# 997: 0.548256997 0.08583757
# 998: 0.059029650 0.22892575
# 999: 0.495523291 0.33242952
# 1000: 0.007417523 0.95179901
它的用途:
dat[, rbindlist(Map(aed, names(.SD), .SD))]
# Column_Name mean st min p1 p5 p25 median p75 p95 p99 max rangeic
# <char> <num> <num> <num> <num> <num> <num> <num> <num> <num> <num> <num> <num>
# 1: V1 0.4882555 0.2914302 0.0002388966 0.006891313 0.04862636 0.2294261 0.4803411 0.7439418 0.9445328 0.9826610 0.9984908 0.5145157
# 2: V2 0.4970157 0.2961325 0.0003734785 0.010906180 0.04513135 0.2385863 0.5024530 0.7563358 0.9514749 0.9927716 0.9997632 0.5177495
【讨论】:
首先,感谢您的解决方案并感谢您提供有关 Rbind 的提示。只是为了好奇,你知道为什么dat[,paste0(colnames(dat)[i])]
不像dat[,"V1"]
那样工作吗?
是的,因为data.table
的 NSE 有点不同。使用data.table
对象,您可以执行dat[,paste0(colnames(dat)[i]),with=FALSE]
来强制执行您想要的操作,它会返回一个1 列data.table
;或者您可以使用as.data.frame(dat)[,paste0(colnames(dat)[i])]
强制(至少暂时)到data.frame
,它会返回一个向量。顺便说一句,paste0
在这一切中什么都不做,只需在您喜欢的任何变体中使用dat[,colnames(dat)[i]]
。
另一种选择:您有一个列号,只需使用它:dat[,i]
返回一个 1 列 data.table
; as.data.frame(dat)[,i]
返回一个向量; dat[[i]]
总是返回一个向量,不管data.table
或data.frame
。
如果将函数的最后两行替换为 c(Column_Name = nm, as.list(vals))
,则可以避免处理矩阵创建和 cbinding以上是关于如何在数据表列中进行循环?的主要内容,如果未能解决你的问题,请参考以下文章
在C#中进行DataTable操作:根据列数据插入一些汇总行