如何在数据表列中进行循环?

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.tableas.data.frame(dat)[,i] 返回一个向量; dat[[i]] 总是返回一个向量,不管data.tabledata.frame 如果将函数的最后两行替换为 c(Column_Name = nm, as.list(vals)),则可以避免处理矩阵创建和 cbinding

以上是关于如何在数据表列中进行循环?的主要内容,如果未能解决你的问题,请参考以下文章

如何在R语言中用循环语句求一列中每24个数的均值

循环通过过滤的数据框以查看值是不是在列表列中

在C#中进行DataTable操作:根据列数据插入一些汇总行

如何在数据框列中附加值

如何在 Hive SQL 中对一列中的数据进行分组并将其分布在另一列中?

我们如何在foreach循环中划分3列中的行