Имеете дело с неполными делами и вменением? - PullRequest
0 голосов
/ 01 мая 2018

У меня есть такой фрейм данных:

df <- data_frame('col1' = c(NA, 1, 2), 'col2' = c(34, NA, 44), 'indicator' = c(1,1,0))

Я использовал complete.cases, чтобы отметить все незавершенные случаи.

Теперь я хочу заменить значения NA на 10, если indicator == 1 и 0 в противном случае для каждого столбца.

Попытка сделать это с apply и MARGIN = 2.

Посоветуйте, пожалуйста, как выполнить такую ​​задачу.

Ответы [ 3 ]

0 голосов
/ 01 мая 2018

Просто и понятно:

df$col1[ is.na(df$col1) ] <- ifelse(df$indicator == 1, 10, 0)
df$col2[ is.na(df$col2) ] <- ifelse(df$indicator == 1, 10, 0)

Если у вас много столбцов, просто используйте цикл for:

for (col in c("col1", "col2")) { 
  df[ is.na(df[[col]]), col] <- ifelse(df$indicator == 1, 10, 0)
}
0 голосов
/ 01 мая 2018

Хотя у вас уже есть ответ, вы вполне можете использовать apply, как указано в вопросе:

df <- data.frame('col1' = c(NA, 1, 2), 
                 'col2' = c(34, NA, 44), 
                 'indicator' = c(1,1,0), 
                 stringsAsFactors = F)

# columns in question
cols <- colnames(df)[!colnames(df) %in% c('indicator')]

# apply it row-wise
# using a nested ifelse call
df[cols] <- apply(df[cols], 2, function(x) {
  y <- ifelse(is.na(x),
              ifelse(df$indicator == 1, 10, 0),
              x)
  y
})
df

Или с меньшим количеством пробела:

df[cols] <- apply(df[cols], 2, function(x) {
  (y <- ifelse(is.na(x), ifelse(df$indicator == 1, 10, 0), x))
})

Это дает

  col1 col2 indicator
1   10   34         1
2    1   10         1
3    2   44         0
0 голосов
/ 01 мая 2018

Мы можем использовать mutate_at от dplyr. Укажите интересующие столбцы в аргументе vars для mutate_at, внутри funs, создайте логическое условие с case_when для замены значениями, которые удовлетворяют условию

library(dplyr)
df %>%
  mutate_at(vars(matches("col\\d+")), 
       funs(case_when(is.na(.) & as.logical(indicator)~ 10, 
                      is.na(.) & !indicator ~ 0,  
                      TRUE ~ .)))
# A tibble: 3 x 3
#   col1  col2 indicator
#    <dbl> <dbl>     <dbl>
# 1    10    34         1
# 2     1    10         1 
# 3     2    44         0

Это также можно сделать с помощью data.table

library(data.table)
setDT(df)
for(j in names(df)[1:2]) {
  i1 <- is.na(df[[j]]) 
  i2 <-  as.logical(df[['indicator']])

  set(df, i = which(i1 & i2), j = j, value = 10)
  set(df, i = which(i1 & !i2), j = j, value = 0)
 }

Если мы хотим, чтобы максимум столбца вместо 10 заменял значения NA, где «индикатор» равен 1, используйте max

df %>%
  mutate_at(vars(matches("col\\d+")), 
       funs(case_when(is.na(.) & as.logical(indicator)~ max(., na.rm = TRUE), 
                      is.na(.) & !indicator ~ 0,  
                      TRUE ~ .)))
# A tibble: 3 x 3
#  col1  col2 indicator
#  <dbl> <dbl>     <dbl>
#1     2    34         1
#2     1    44         1
#3     2    44         0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...