在R中使用for循环和mutate函数生成新变量

时间:2018-08-28 20:13:27

标签: r loops for-loop dplyr mutate

假设我有一个看起来像这样的数据框:

fact_code style_serial ss rib button rib_s button_s
1008      style_1018   1   0  0      1     1 
1008      style_1018   0   1  0      1     1
1008      style_1018   0   1  0      1     1
1008      style_1018   0   0  1      1     1 
1008      style_1003   1   0  1      0     1
1008      style_1003   0   0  1      0     1
1008      style_1003   0   0  0      0     1
1008      style_1003   0   0  0      0     1
1004      style_1197   1   0  0      1     0 
1004      style_1197   0   0  0      1     0
1004      style_1197   0   0  0      1     0
1004      style_1197   0   1  0      1     0

关键变量,肋骨和按钮是虚拟变量。它们指示工厂生产的特定服装款式是否具有罗纹或纽扣或两者兼有。然后,我想利用fact_codestyle_serial分组的这些虚拟变量中的最大值,在这种情况下,我将它们分别命名为rib_sbutton_s

变量rib_sbutton_s的生成如下:

df <- df %>% group_by(fact_code, style_serial) %>% mutate(rib_s = max(rib, na.rm = TRUE))
df <- df %>% group_by(fact_code, style_serial) %>% mutate(button_s = max(button, na.rm = TRUE))

现在假设我有大约20个这样的变量。我想创建一个循环,该循环运行的次数与变量的数量相同,并且每次都针对20个虚拟变量中的每一个执行上述代码。

我已经尝试将这两个变量作为测试:

for (xx in c("rib", "button")){
df <- df %>%
group_by_(fact_code, style_serial) %>%
yy <- paste0(c(xx, "s"), collapse = "_") %>%
mutate_(yy = max(xx, na.rm = TRUE))
}

但是它给了我以下错误信息:

Error in UseMethod("mutate_") : no applicable method for 'mutate_' applied to an object of class "character"

我也尝试了诸如tapplyaggregate之类的基本r函数,但是总是收到一些错误消息。

您有办法解决这个问题吗?

2 个答案:

答案 0 :(得分:2)

使用dplyr::mutate_at可以非常简洁地解决此问题:

library(dplyr)
key <- c("rib", "button")
df %>%
    group_by(fact_code, style_serial) %>%
    mutate_at(vars(key), funs(max = max(.)))
## A tibble: 12 x 9
## Groups:   fact_code, style_serial [3]
#   fact_code style_serial    ss   rib button rib_s button_s rib_max button_max
#       <int> <fct>        <int> <int>  <int> <int>    <int>   <dbl>      <dbl>
# 1      1008 style_1018       1     0      0     1        1      1.         1.
# 2      1008 style_1018       0     1      0     1        1      1.         1.
# 3      1008 style_1018       0     1      0     1        1      1.         1.
# 4      1008 style_1018       0     0      1     1        1      1.         1.
# 5      1008 style_1003       1     0      1     0        1      0.         1.
# 6      1008 style_1003       0     0      1     0        1      0.         1.
# 7      1008 style_1003       0     0      0     0        1      0.         1.
# 8      1008 style_1003       0     0      0     0        1      0.         1.
# 9      1004 style_1197       1     0      0     1        0      1.         0.
#10      1004 style_1197       0     0      0     1        0      1.         0.
#11      1004 style_1197       0     0      0     1        0      1.         0.
#12      1004 style_1197       0     1      0     1        0      1.         0.

这将自动计算key中给定变量的最大值(每组),并通过将_max附加到相应的列名来创建新列。请注意,如果您还可以在select中使用通常的contains语义(例如matchesstarts_withends_withvars(...)等)不想(或不能)事先定义key


样本数据

df <- read.table(text =
    "fact_code style_serial ss rib button rib_s button_s
1008      style_1018   1   0  0      1     1
1008      style_1018   0   1  0      1     1
1008      style_1018   0   1  0      1     1
1008      style_1018   0   0  1      1     1
1008      style_1003   1   0  1      0     1
1008      style_1003   0   0  1      0     1
1008      style_1003   0   0  0      0     1
1008      style_1003   0   0  0      0     1
1004      style_1197   1   0  0      1     0
1004      style_1197   0   0  0      1     0
1004      style_1197   0   0  0      1     0
1004      style_1197   0   1  0      1     0", header = T)

答案 1 :(得分:0)

对不起,我不在电脑旁,所以我无法尝试修复它,但是当您希望数据框很长时,看来您的数据帧确实很宽。您是否考虑过使用collect()将值是1的列的实际名称替换为布尔值0或1的所有列?

我认为正在生成错误,因为您不能一次在单个行上使用mutate。也许如果您尝试先添加一个临时列,然后尝试将其填充到循环中?