【问题标题】:Fixing function error: 'pairlist' object cannot be coerced to type 'double'修复函数错误:“pairlist”对象不能被强制输入“double”
【发布时间】:2020-07-14 17:10:21
【问题描述】:

我编写了一个函数来汇总三个数据集中的相同数值变量。当我将 x 替换为实际的变量名时,此代码在函数之外工作。

k1 <- data.frame(variable_name = rnorm(100), year = sample(x = 1990:1995, size = 100, replace = TRUE))
k2 <- data.frame(variable_name = rnorm(100), year = sample(x = 1990:1995, size = 100, replace = TRUE))
k3 <- data.frame(variable_name = rnorm(100), year = sample(x = 1990:1995, size = 100, replace = TRUE))

numeric_var_summary <- function(x) {
  
  x <- enquo(x)

  k1_x <- k1 %>%
    select(year, !!x) %>%
    group_by(year) %>%
    summarize(min = min(!!x), Q1 = quantile(!!x, 0.25), median = median(!!x), 
              Q3 = quantile(!!x, 0.75), max = max(!!x), Qrange = quantile(!!x, 0.75) - quantile(!!x, 0.25), 
              mean = mean(!!x), sd = sd(x), n = n(), 
              missing = sum(is.na(!!x)))
  
  k2_x <- k2 %>%
    select(xear, !!x) %>%
    group_by(year) %>%
    summarize(min = min(!!x), Q1 = quantile(!!x, 0.25), median = median(!!x), 
              Q3 = quantile(!!x, 0.75), max = max(!!x), Qrange = quantile(!!x, 0.75) - quantile(!!x, 0.25), 
              mean = mean(!!x), sd = sd(!!x), n = n(), 
              missing = sum(is.na(!!x)))
  
  k3_x <- k3 %>%
    select(year, !!x) %>%
    group_by(year) %>%
    summarize(min = min(!!x), Q1 = quantile(x, 0.25), 
              median = median(!!x), Q3 = quantile(!!x, 0.75),
              max = max(!!x), Qrange = quantile(!!x, 0.75) - quantile(!!x, 0.25), 
              mean = mean(!!x), sd = sd(!!x), n = n(),
              missing = sum(is.na(!!x)))
  
  return(bind_rows(k1_x, k2_x, k3_x), n = Inf)
  
  
}

numeric_var_summary(x = variable_name)

但是当我尝试运行该函数时出现此错误:

Error in is.data.frame(x) : 
  'pairlist' object cannot be coerced to type 'double' 

我想知道这是否是整洁评估的问题?不确定我是否正确地这样做了。感谢您的帮助。

【问题讨论】:

  • 如果您包含一个简单的reproducible example,其中包含可用于测试和验证可能解决方案的示例输入和所需输出,则更容易为您提供帮助。定义变量k1k2等,这样我们就可以实际运行代码了。
  • 现在当我运行你提供的代码时,我没有得到同样的错误。我得到“不能对不存在的列进行子集化。x 列 year 不存在。”。您正在使用 x=variable_name 调用该函数,但这不是您的 k1 数据中的列名。请确保您的示例是可重现的。
  • 示例现在应该可以重现了。
  • 我仍然得到一个不同的错误。我得到“summarise() 输入 sd 的问题。不能强制 x '语言'对象键入'double'”这可能是因为您在创建k1_x 时使用了sd(x) 而不是sd(!!x)。似乎还有一个quantile(x, 0.25) 缺少!! 以及“xear”而不是“year”的拼写错误。请仔细检查您的代码。
  • 现在可以使用了。就像你说的那样,有一些失踪的!!。非常感谢。

标签: r tidyverse


【解决方案1】:

dplyr 1.0 开始,有两种方法可以解决这个问题:

  • 如果您想将列标识符作为裸表达式传递,就像您在示例中所做的那样,请使用{{x}}
  • 或者,您可以将其作为字符向量传递,然后使用.data[[x]]

我将使用第一种方法,因为这最接近您的目标。

由于您在所有三个数据帧中计算相同的摘要,因此您的函数也可以更加简洁。在这里,我使用purrr::map_dfr 应用一个函数,将您的一个数据帧汇总到所有三个数据帧,然后对结果进行行绑定:

library(dplyr)
library(purrr)

set.seed(3046)

k1 <- data.frame(variable_name = rnorm(100), year = sample(x = 1990:1995, size = 100, replace = TRUE))
k2 <- data.frame(variable_name = rnorm(100), year = sample(x = 1990:1995, size = 100, replace = TRUE))
k3 <- data.frame(variable_name = rnorm(100), year = sample(x = 1990:1995, size = 100, replace = TRUE))


numeric_var_summary <- function(k, col, na.rm = TRUE) {
  
  k_summary <- k %>%
    select(year, {{col}}) %>%
    group_by(year) %>%
    summarize(min = min({{col}}, na.rm = na.rm), 
              Q1 = quantile({{col}}, 0.25, na.rm = na.rm),
              median = median({{col}}, na.rm = na.rm), 
              Q3 = quantile({{col}}, 0.75, na.rm = na.rm), 
              max = max({{col}}, na.rm = na.rm), 
              Qrange = quantile({{col}}, 0.75, na.rm = na.rm) - quantile({{col}}, 0.25, na.rm = na.rm), 
              mean = mean({{col}}, na.rm = na.rm), 
              sd = sd({{col}}, na.rm = na.rm), 
              n = n(), 
              missing = sum(is.na({{col}})))
  
  return(k_summary)
  
}


# compute the individual summaries and combine the results
map_dfr(list(k1, k2, k3), numeric_var_summary, col = variable_name)

#> `summarise()` ungrouping output (override with `.groups` argument)
#> `summarise()` ungrouping output (override with `.groups` argument)
#> `summarise()` ungrouping output (override with `.groups` argument)
#> # A tibble: 18 x 11
#>     year    min     Q1  median    Q3   max Qrange    mean    sd     n missing
#>    <int>  <dbl>  <dbl>   <dbl> <dbl> <dbl>  <dbl>   <dbl> <dbl> <int>   <int>
#>  1  1990 -1.18  -1.06  -0.553  0.312 2.72   1.37  -0.0309 1.38      9       0
#>  2  1991 -2.73  -0.775 -0.245  0.163 0.849  0.938 -0.471  0.954    18       0
#>  3  1992 -1.01  -0.176  0.354  0.735 2.75   0.911  0.344  0.849    21       0
#>  4  1993 -0.681 -0.247 -0.0524 0.567 1.99   0.814  0.256  0.799    14       0
#>  5  1994 -1.84  -1.08  -0.157  0.287 1.80   1.37  -0.280  0.948    18       0
#>  6  1995 -1.20  -0.573 -0.261  0.720 1.97   1.29   0.0397 0.881    20       0
#>  7  1990 -1.76  -0.397  0.283  0.534 1.29   0.931  0.0240 0.870    22       0
#>  8  1991 -2.24  -0.496 -0.112  0.372 1.29   0.868 -0.137  1.01     11       0
#>  9  1992 -1.44  -0.241  0.711  1.17  2.51   1.41   0.449  1.16     12       0
#> 10  1993 -1.92  -0.858 -0.210  0.770 2.31   1.63  -0.0219 1.11     22       0
#> 11  1994 -1.41  -0.207  0.485  0.870 2.23   1.08   0.332  0.987    14       0
#> 12  1995 -2.86  -0.374  0.300  1.05  2.35   1.43   0.221  1.24     19       0
#> 13  1990 -1.49  -1.03  -0.206  0.113 0.851  1.14  -0.292  0.722    14       0
#> 14  1991 -1.67  -0.454  0.139  0.514 1.82   0.968  0.0963 0.956    19       0
#> 15  1992 -2.11  -1.02  -0.217  0.569 1.10   1.59  -0.344  0.986    16       0
#> 16  1993 -1.58  -0.935 -0.0794 0.625 1.26   1.56  -0.160  0.946    10       0
#> 17  1994 -1.93  -0.494 -0.307  0.294 1.60   0.788 -0.186  0.902    22       0
#> 18  1995 -1.49  -0.751  0.374  0.900 2.19   1.65   0.229  1.10     19       0


# verify that the simplified function returns identical results:

numeric_var_summary_manual <- function(x) {
  
  k1_x <- k1 %>%
    select(year, {{x}}) %>%
    group_by(year) %>%
    summarize(min = min({{x}}), Q1 = quantile({{x}}, 0.25), median = median({{x}}), 
              Q3 = quantile({{x}}, 0.75), max = max({{x}}), Qrange = quantile({{x}}, 0.75) - quantile({{x}}, 0.25), 
              mean = mean({{x}}), sd = sd({{x}}), n = n(), 
              missing = sum(is.na({{x}})))
  
  k2_x <- k2 %>%
    select(year, {{x}}) %>%
    group_by(year) %>%
    summarize(min = min({{x}}), Q1 = quantile({{x}}, 0.25), median = median({{x}}), 
              Q3 = quantile({{x}}, 0.75), max = max({{x}}), Qrange = quantile({{x}}, 0.75) - quantile({{x}}, 0.25), 
              mean = mean({{x}}), sd = sd({{x}}), n = n(), 
              missing = sum(is.na({{x}})))
  
  k3_x <- k3 %>%
    select(year, {{x}}) %>%
    group_by(year) %>%
    summarize(min = min({{x}}), Q1 = quantile({{x}}, 0.25), 
              median = median({{x}}), Q3 = quantile({{x}}, 0.75),
              max = max({{x}}), Qrange = quantile({{x}}, 0.75) - quantile({{x}}, 0.25), 
              mean = mean({{x}}), sd = sd({{x}}), n = n(),
              missing = sum(is.na({{x}})))
  
  return(bind_rows(k1_x, k2_x, k3_x))
  
  
}


identical(numeric_var_summary_manual(x = variable_name),
          map_dfr(list(k1, k2, k3), numeric_var_summary, col = variable_name))

#> `summarise()` ungrouping output (override with `.groups` argument)
#> `summarise()` ungrouping output (override with `.groups` argument)
#> `summarise()` ungrouping output (override with `.groups` argument)
#> `summarise()` ungrouping output (override with `.groups` argument)
#> `summarise()` ungrouping output (override with `.groups` argument)
#> `summarise()` ungrouping output (override with `.groups` argument)
#> [1] TRUE

【讨论】:

  • 这很棒。我知道必须有一种方法来简化我的代码,但不知道map_dfr。我们使用这个函数是因为我们有list(k1, k2, k3)吗?
  • 是的。 purrr 拥有一系列 map* 函数,它们接受一个列表并将某些函数应用于每个列表元素。如果我们只是在列表中调用map 而不是map_dfr,我们会得到一个列表(在这种情况下,是一个数据帧列表)。在 R 中有很多其他方法可以做到这一点,但我发现 purrr 最直观。
猜你喜欢
  • 2017-08-29
  • 2016-05-22
  • 1970-01-01
  • 2016-09-30
  • 2016-05-24
  • 1970-01-01
  • 2012-01-17
  • 2023-03-26
  • 1970-01-01
相关资源
最近更新 更多