【问题标题】:how to get summary in a loop in如何在循环中获取摘要
【发布时间】:2020-05-14 19:57:54
【问题描述】:

我正在尝试以某种方式计算循环中的汇总统计信息(平均值、中值、最小值、最大值),但下面的循环没有运行。任何帮助将不胜感激。

sstat<-function(x){

Table <- tablez %>% 
           filter(Date==max(Date)) %>%
           summarise(rate_dq_re=x(rate_dq_re), 
                     rate_dq_nre=x(rate_dq_nre))
Table
}

# Summary Statistics I need to compute:
stats <- c("min","median","mean","max")

for(stats in stats) {
  sstat(stats) # THIS IS NOT WORKING- Error: couldn't find function "x"
}

【问题讨论】:

  • 试试for (stat in stats),只使用stat而不是stats[stats]
  • 你想做什么? for循环和你定义的Table之间的联系在哪里?
  • 感谢您的建议。抱歉,我没有错误地发布整个代码。我正在更新它。我按照你之前的建议还是不行

标签: r


【解决方案1】:

我稍微更改了您的代码,但我认为现在它可以正常工作了:

df <- data.frame(alpha=1:100)

sstat <- function(df, fun){
  Table <- df %>% 
    summarise(rate_dq_re=fun(alpha))
  return(Table)
}

# Summary Statistics I need to compute:
stats <- c("min","median","mean","max")

for(stat in stats) {
  df %>%
    sstat(eval(parse(text=stat))) %>%
    print()
}

# another version of your for-loop
for(stat in stats) {
  stat %>%
    parse(text=.) %>%
    eval() %>%
    sstat(df, .) %>%
    print()
}

由于您没有提供任何数据,我只是创建了一个带有一些虚拟值的 data.frame 并相应地更改了您的函数sstat

  1. 函数sstat 现在将您的数据和一个函数作为输入并返回汇总表。
  2. for 循环使用stat 作为变量而不是stats。你不能同时使用stats 作为变量 AND 序列,除非你真的想做一些奇怪的事情。
  3. 函数名称由stats 作为字符串提供。 eval(parse(text=.)) 语句使用此字符串并运行它们。
  4. 根据您期望的输出,有几种方法可以删除 for 循环。尝试使用*apply-functions:
sapply(stats, function(stat) sstat(df, eval(parse(text=stat))))
# or
lapply(stats, function(stat) sstat(df, eval(parse(text=stat))))

避免eval(parse(text=.))

您可以使用get(stat),而不是使用eval(parse(text=stat))

【讨论】:

    【解决方案2】:

    使用dplyr::summarise() 不需要循环汇总。以下代码采用输入数据框和列,并计算指定列的多个统计信息。

    library(dplyr)
    
    sumstats <- function(df,colName){
         df %>% summarise(minimum = min({{colName}}),
                          avg = mean({{colName}}),
                          med = median({{colName}}),
                          maximum = max({{colName}}))
    }
    
    sumstats(mtcars,mpg)
    

    ...和输出:

    > sumstats(mtcars,mpg)
      minimum      avg  med maximum
    1    10.4 20.09062 19.2    33.9
    > 
    

    最初的问题包括对数据进行子集化的步骤。我们可以将过滤器表达式作为可选参数添加到 sumstats() 函数,使用 missing() 函数检查它,并有条件地对数据进行子集化。我们还将计算统计中使用的观察次数,以便我们可以看到对数据进行子集化对结果的影响。

    sumstats <- function(df,colName,aFilter=NULL) {
         if(missing(aFilter)) subset <- df
         else subset <- filter(df,{{aFilter}})
         subset %>% 
                summarise(n = n(),
                          minimum = min({{colName}}),
                          avg = mean({{colName}}),
                          med = median({{colName}}),
                          maximum = max({{colName}})) 
    }
    

    首先,我们将在整个数据框内为mtcars$cyl 生成汇总统计信息。请注意,结果与先前生成的结果匹配,并添加了n = 32

    > sumstats(mtcars,mpg)
       n minimum      avg  med maximum
    1 32    10.4 20.09062 19.2    33.9
    >
    

    其次,我们将运行 4 缸汽车的汇总统计数据。

    > sumstats(mtcars,mpg,cyl == 4)
       n minimum      avg med maximum
    1 11    21.4 26.66364  26    33.9
    >
    

    我们将通过使用不同方法检查平均数和观察次数来验证结果。

    > # check the mean 
    > mean(mtcars$mpg[mtcars$cyl == 4])
    [1] 26.66364
    > # check number of obs
    > nrow(mtcars[mtcars$cyl ==4,])
    [1] 11
    >
    

    【讨论】:

    • 非常感谢莱恩。这并不能完全解决我正在寻找的东西。但这是解决问题的另一种好方法。非常感谢您的帮助。
    • @SaurabhDatta - 感谢您的反馈,Saurabh。对于大数据量,在数据帧的单次传递中计算多个统计信息的解决方案将比必须多次遍历相同数据的解决方案运行得更快。例如,如果我们构建 1000 万行随机数据并通过 Martin 的解决方案和我的解决方案运行它,我的运行速度大约快 20%。对于单个列而言,它并不重要,但如果您要以这种方式汇总数百列,则改进的响应时间变得有意义。
    • 再次感谢 Len。我完全赞成你。我目前正在处理一个小型数据集,但将来计划应用于大型数据集。您的解决方案对我也很有用。
    猜你喜欢
    • 2020-12-29
    • 1970-01-01
    • 2016-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-11
    相关资源
    最近更新 更多