首页 > 解决方案 > 在 dplyr 中的另一列基础上添加新列并不能像我猜的那样工作

问题描述

我是 R 新手,我想使用 dplyr 在另一列基础上创建一个新列。我在网上阅读了解决方案,但我的问题并不顺利。

我有一个范围数据集(以字符串形式),如下所示:

df = data.frame(my_range = c("0-14", "15-24", "25-34"))
  my_range
1     0-14
2    15-24
3    25-34

我可以使用以下代码计算这些字符串的平均值:

> mean(as.integer(unlist(strsplit("0-14", "-"))))
> 7

我想创建一个名为的新列range_mean,其中包含列中每个元素的平均值my_range。我认为这可能会奏效:

> library(dplyr)
> df %>%
+ mutate(range_mean = mean(as.integer(unlist(strsplit(my_range, "-")))))

但结果不是我想的那样。我不明白为什么会这样:

  my_range range_mean
1     0-14   18.66667
2    15-24   18.66667
3    25-34   18.66667

我试图研究以找到解决方案,但我失败了。我在这里问我怎样才能创建一个这样的新列?

  my_range range_mean
1     0-14   7
2    15-24   19.5
3    25-34   29.5

标签: rdplyr

解决方案


一个选项是separate将列分成两个数值列 ( remove = FALSE),然后使用map2循环遍历相应的列,获取mean元素向量的

library(dplyr)
library(purrr)
library(tidyr)
df %>%
   separate(my_range, into = c('start', 'end'), convert = TRUE,
      remove = FALSE) %>%
   transmute(my_range, range_mean = map2_dbl(start, end, ~ mean(c(.x, .y))))

-输出

# my_range range_mean
#1     0-14        7.0
#2    15-24       19.5
#3    25-34       29.5

问题是unlist没有列出整个列,因此该mean列上的值是所有值的平均值,除非有分组,即使用 OP 的代码,我们可以添加rowwise

df %>% 
   rowwise %>%
   mutate(range_mean = mean(as.integer(unlist(strsplit(my_range, "-"))))) %>%
   ungroup

-输出

# A tibble: 3 x 2
#  my_range range_mean
#  <chr>         <dbl>
#1 0-14            7  
#2 15-24          19.5
#3 25-34          29.5

或者它可以像rowMeans矢量化选项一样简化

rowMeans(read.table(text = df$my_range, sep="-", header = FALSE))
#[1]  7.0 19.5 29.5

推荐阅读