Создание переменной / столбца в тех же данных для подмножества данных с использованием dplyr и mutate - PullRequest
0 голосов
/ 04 сентября 2018

У меня есть данные в R, которые выглядят следующим образом

fact_code style_serial mach_smv
1004      style_1200   0.15
1004      style_1200   0
1004      style_1200   0.30
1004      style_1203   0
1004      style_1203   0.22
1004      style_1203   0.18
1008      style_1120   0.25
1008      style_1120   0.25
1008      style_1120   1
1008      style_1121   0.3
1008      style_1121   0
1008      style_1121   0.6

Я хотел бы создать переменную avg_mach_smv для существующих данных, которая принимает среднее значение переменной mach_smv при mach_smv != 0, а в противном случае - NA.

Пример приведен ниже:

fact_code style_serial mach_smv avg_mach_smv
1004      style_1200   0.15     0.225
1004      style_1200   0        NA
1004      style_1200   0.30     0.225
1004      style_1203   0        NA
1004      style_1203   0.22     0.2
1004      style_1203   0.18     0.2
1008      style_1120   0.25     0.5
1008      style_1120   0.25     0.5
1008      style_1120   1        0.5
1008      style_1121   0.3      0.45
1008      style_1121   0        NA
1008      style_1121   0.6      0.45

Код Stata, используемый для генерации переменной:

bysort fact_code: egen sum_nmachines=sum(nmachines) if ss==1

Однако я хотел бы знать, как приведенный выше код или эту переменную можно сгенерировать с помощью R.

Это первый код, который я пробовал:

df <- df %>%
select(fact_code, ss, style_serial, machine_name, process_smv, help, 
mach_smv) %>%
group_by(fact_code, style_serial) %>%
filter(mach_smv != 0) %>%
mutate(avg_mach_smv = mean(mach_smv, na.rm = TRUE))

К сожалению, это то, что я не ищу, так как он отбрасывает те строки, где mach_smv == 0, а это не то, что я хочу.

Я также попробовал следующие коды ниже, но либо получаю ошибку, либо получаю неверные значения:

df2 <- df %>%
select(fact_code, ss, style_serial, machine_name, process_smv, help, 
mach_smv) %>%
group_by(fact_code, style_serial) %>%
mutate(avg_mach_smv = if_else(mach_smv != 0, mean(mach_smv, na.rm = TRUE), 
NA_real_))

df2 <- df %>%
select(fact_code, style_serial, mach_smv) %>%
group_by(fact_code, style_serial) %>%
mutate_at(mach_smv != 0, funs(mean(mach_smv, na.rm = TRUE)))

Есть предложения о том, как создать переменную?

Ответы [ 3 ]

0 голосов
/ 04 сентября 2018

На всякий случай, альтернативой с использованием data.table можно попробовать

library(data.table)
setDT(df)[,.(Mean=ifelse(mach_smv!=0,mean(mach_smv[mach_smv!=0]),NA)),
              by=.(fact_code, style_serial)]

, который возвращает

    fact_code style_serial  Mean
 1:      1004   style_1200 0.225
 2:      1004   style_1200    NA
 3:      1004   style_1200 0.225
 4:      1004   style_1203    NA
 5:      1004   style_1203 0.200
 6:      1004   style_1203 0.200
 7:      1008   style_1120 0.500
 8:      1008   style_1120 0.500
 9:      1008   style_1120 0.500
10:      1008   style_1121 0.450
11:      1008   style_1121    NA
12:      1008   style_1121 0.450
0 голосов
/ 04 сентября 2018

Вот вариант с использованием base R

i1 <-  df$mach_smv != 0
df$avg_mach_smv[i1] <- with(df[i1,], ave(mach_smv, fact_code, style_serial))
df
#   fact_code style_serial mach_smv avg_mach_smv
#1       1004   style_1200     0.15        0.225
#2       1004   style_1200     0.00           NA
#3       1004   style_1200     0.30        0.225
#4       1004   style_1203     0.00           NA
#5       1004   style_1203     0.22        0.200
#6       1004   style_1203     0.18        0.200
#7       1008   style_1120     0.25        0.500
#8       1008   style_1120     0.25        0.500
#9       1008   style_1120     1.00        0.500
#10      1008   style_1121     0.30        0.450
#11      1008   style_1121     0.00           NA
#12      1008   style_1121     0.60        0.450

Или используя tidyverse

library(tidyverse)
df %>%
  group_by(fact_code, style_serial)  %>%
  mutate(avg_mach_smv = case_when(mach_smv !=0 ~ mean(mach_smv[mach_smv != 0]), 
                             TRUE ~ NA_real_))

Данные

df <- structure(list(fact_code = c(1004L, 1004L, 1004L, 1004L, 1004L, 
1004L, 1008L, 1008L, 1008L, 1008L, 1008L, 1008L), style_serial = c("style_1200", 
"style_1200", "style_1200", "style_1203", "style_1203", "style_1203", 
"style_1120", "style_1120", "style_1120", "style_1121", "style_1121", 
"style_1121"), mach_smv = c(0.15, 0, 0.3, 0, 0.22, 0.18, 0.25, 
0.25, 1, 0.3, 0, 0.6)), class = "data.frame", row.names = c(NA, 
-12L))
0 голосов
/ 04 сентября 2018

С помощью ifelse мы можем проверить условие mach_smv==0 и принять mean, игнорируя 0 значений.

library(dplyr)
df %>%
  group_by(fact_code, style_serial) %>%
  mutate(avg_mach_smv = ifelse(mach_smv == 0, NA, mean(mach_smv[mach_smv != 0])))


#   fact_code style_serial mach_smv avg_mach_smv
#       <int> <fct>           <dbl>        <dbl>
# 1      1004 style_1200       0.15        0.225
# 2      1004 style_1200       0           NA    
# 3      1004 style_1200       0.3         0.225
# 4      1004 style_1203       0           NA    
# 5      1004 style_1203       0.22        0.2  
# 6      1004 style_1203       0.18        0.2  
# 7      1008 style_1120       0.25        0.5  
# 8      1008 style_1120       0.25        0.5  
# 9      1008 style_1120       1           0.5  
#10      1008 style_1121       0.3         0.450
#11      1008 style_1121       0           NA    
#12      1008 style_1121       0.6         0.450
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...