我有一个这样的数据框:
df <- data_frame('col1' = c(NA, 1, 2), 'col2' = c(34, NA, 44), 'indicator' = c(1,1,0))
我使用complete.cases
标记了所有不完整的案例。
现在我要做的是用10
替换NA值,如果indicator == 1
,则替换0
。
尝试使用apply
和MARGIN = 2
。
请告知如何执行此类任务。
答案 0 :(得分:3)
我们可以使用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来替换“指标”为1的NA
值,请使用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
答案 1 :(得分:2)
虽然您已经得到答案,但您可以按照问题中的要求使用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
答案 2 :(得分:1)
简单明了:
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)
}