【问题标题】:Summarise numeric columns, return last value of non-numeric汇总数字列,返回非数字的最后一个值
【发布时间】:2018-08-23 04:50:32
【问题描述】:

想要汇总数据框或 tibble 的数字列,同时对非数字列执行其他操作,这种情况并不少见。

这个here 有一个不错的技巧,但是对于字符列来说似乎失败了。

首先,它正在工作,返回数字列的平均值和其他列第一行的值

set.seed(1234)
category <- (c('A','A','E','E','B','B','C'))
date <- seq(as.Date("2017-01-01"), by = "month", length.out = 7)
value1 <- sample(seq(from = 91, to = 97, by = 1))
dt <- data.frame(category, date, value1)
dt<- as_tibble(dt)
#works
dt2<- dt %>%
  group_by(category) %>%
  summarise_all(funs(if_else(is.numeric(.), mean(.), last(.))))
print(dt2)

注意,因为日期列是非数字的,所以它返回最后一行的值而不是平均值:

# A tibble: 4 x 3
  category date       value1
  <fct>    <date>      <dbl>
1 A        2017-02-01   92.5
2 B        2017-06-01   93.5
3 C        2017-07-01   97  
4 E        2017-04-01   94.5

但是,当其中一列是 chr 时,它会失败

marsupial <-c("quoll","phascogale",'triok','opossum','antechinus','bandicoot','Fat-tailed dunnart')
dt$marsupial <- marsupial
dt3<- dt %>% #doesn't work
  group_by(category) %>%
  summarise_all(funs(if_else(is.numeric(.), mean(.), last(.))))
print(dt3)

给出这些错误:

Error in summarise_impl(.data, dots) : 
  Evaluation error: `false` must be type double, not character.
In addition: Warning message:
In mean.default(marsupial) :
  argument is not numeric or logical: returning NA

我假设'false' must be type double 指的是有袋动物的列,导致尝试评估last。如果是这样,为什么它必须是双重的,还有其他方法吗?我不会从传统的 if/else 条件中期待这一点。

【问题讨论】:

  • summarise_if(is.numeric, mean)
  • 如果你想保持当前的结构,问题是因为dplyr::if_else 对类型很严格。 ifelseif ... else ... 工作。不过,前者会删除日期属性,这很烦人,所以if (is.numeric(.)) mean(.) else last(.) 可能是最好的。
  • @alistaire 使用if (is.numeric(.)) mean(.) else last(.) 我得到这个错误:Error in summarise_impl(.data, dots) : Column "date" must be length 1 (a summary value), not 7 但也许我误解了如何使用它,是的ifelse 删除了日期属性。

标签: r dplyr


【解决方案1】:

ifelse 似乎是问题所在,所以我创建了一个函数。我已经更新了我的答案。我已经在日期属性上对其进行了测试,它似乎也适用于列表。希望能解决你的问题:

dt %>% group_by(category) %>%
  summarise_all(function(x){
  if(is.numeric(x)){
    return(mean(x))
  }else{
    nth(x,-1)
  }
}
)

【讨论】:

  • 这行得通,但正如@alistaire 所说,它会删除日期属性。 (而且它也不适用于作为列表的列,但我没有要求可以处理该问题的解决方案)。
  • 我已经更新了我的答案。我已经在日期属性上对其进行了测试,它似乎也适用于列表。我希望它能解决你的问题。
  • 非常感谢,这适用于日期!它不适用于我在另一个数据框中的列表列,我得到Error in summarise_impl(.data, dots) : Column "listColumn" must be length 1 (a summary value), not 16 但这不是原始问题的一部分;我必须为此制作一个新的。
【解决方案2】:

截至 2021 年,这是当前语法:

dt %>%
  group_by(category) %>%
  summarise(across(is.numeric, mean),
            across(where(~ !is.numeric(.)), last))

【讨论】:

    猜你喜欢
    • 2012-07-21
    • 2014-06-06
    • 1970-01-01
    • 1970-01-01
    • 2021-03-05
    • 2017-02-10
    • 2018-09-08
    • 2021-02-15
    相关资源
    最近更新 更多