将变量中的值设置为 NA,以另一个变量为条件
Setting a value in a variable to NA, conditional on another variable
如果满足另一个变量的条件,我希望删除变量中的值。例如:
df$var1[df$condvar == 0] <- NA
上面的代码工作正常,但我需要为更多的变量重复此代码,所以上面的 var1
将更改为 var2
、var3
等。这总是基于相同的 condvar
,尽管对于一半的变量,条件是 df$condvar == 1
。一遍又一遍地重复这一行很麻烦,我想知道是否有更简洁的编码方式。 apply
函数之一会有帮助,还是我需要创建自定义函数?
作为可重现的示例,我希望避免以下代码的重复性:
ex <- mtcars
ex$mpg[ex$vs == 0] <- NA
ex$disp[ex$vs == 0] <- NA
ex$drat[ex$vs == 0] <- NA
ex$cyl[ex$vs == 1] <- NA
ex$hp[ex$vs == 1] <- NA
ex$wt[ex$vs == 1] <- NA
ex
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 NA 6 NA 110 NA 2.620 16.46 0 1 4 4
Mazda RX4 Wag NA 6 NA 110 NA 2.875 17.02 0 1 4 4
Datsun 710 22.8 NA 108.0 NA 3.85 NA 18.61 1 1 4 1
Hornet 4 Drive 21.4 NA 258.0 NA 3.08 NA 19.44 1 0 3 1
Hornet Sportabout NA 8 NA 175 NA 3.440 17.02 0 0 3 2
Valiant 18.1 NA 225.0 NA 2.76 NA 20.22 1 0 3 1
Duster 360 NA 8 NA 245 NA 3.570 15.84 0 0 3 4
etc.
如果有一行代码适用于 condvar == 0
的所有变量,另一行适用于 condvar == 1
.
的变量,我会非常高兴
尝试:
ifelse(df$var1 == 0, NA, df$var1)
这是一个希望不会太复杂的尝试。如果设置要循环的vars
,对应的values
要被选中索引,可以这样:
vars <- c("mpg", "disp", "cyl", "hp")
values <- c(0, 0, 1, 1)
ex[vars] <- Map(function(x,y) replace(x, ex$vs == y, NA), ex[vars], vals)
# mpg cyl disp hp drat wt qsec vs am gear carb
#Mazda RX4 NA 6 NA 110 3.90 2.620 16.46 0 1 4 4
#Mazda RX4 Wag NA 6 NA 110 3.90 2.875 17.02 0 1 4 4
#Datsun 710 22.8 NA 108.0 NA 3.85 2.320 18.61 1 1 4 1
#Hornet 4 Drive 21.4 NA 258.0 NA 3.08 3.215 19.44 1 0 3 1
#Hornet Sportabout NA 8 NA 175 3.15 3.440 17.02 0 0 3 2
#Valiant 18.1 NA 225.0 NA 2.76 3.460 20.22 1 0 3 1
# ...
如果你只有两组,你可以通过评论中提到的@HubertL 和@Phil 的几个赋值来更简单地做到这一点,但是使用 Map
允许你考虑许多变量和许多可能的变量索引值,无需超过 3 行代码。
使用新的实验性 case_when
函数的 dplyr 方法将类似于:
require(dplyr)
ex <- mtcars
ex <- ex %>%
mutate(mpg = case_when(.$vs==0 ~ as.double(NA), TRUE ~ .$mpg)) %>%
mutate(disp = case_when(.$vs==0 ~ as.double(NA), TRUE ~ .$disp)) %>%
mutate(cyl = case_when(.$vs==1 ~ as.double(NA), TRUE ~ .$cyl)) %>%
mutate(hp = case_when(.$vs==1 ~ as.double(NA), TRUE ~ .$hp))
备注:
- Hadley 说 on 2016-06-27 "case_when() is still somewhat experiment and does not currently work inside mutate(). That will be fixed in a future version." 我花了 40 分钟才得到这段代码。你明白了。一旦
case_when
起作用,它就会很好。同时 filter()
的解决方法低于
- 您必须使用
.$var
来引用 RHS 上的变量
- 您必须在 RHS 上指定 NA 的类型,因此所有
as.double(NA)
TRUE ~ ...
指定默认子句
使用 filter()
的解决方法:
ex <- rbind(ex %>% filter(vs==0) %>% mutate(mpg=NA, disp=NA),
ex %>% filter(vs==1) %>% mutate(cyl=NA, hp=NA) )
由于 vs
上的拆分,它具有重新排列行的副作用
感谢@HubertL(欢迎post回答这个问题,我会投赞成票)和@smci:
ex[ex$vs == 0, c("mpg", "disp", ...)] <- NA
ex[ex$vs == 1, c("cyl", "hp", ...)] <- NA
如果满足另一个变量的条件,我希望删除变量中的值。例如:
df$var1[df$condvar == 0] <- NA
上面的代码工作正常,但我需要为更多的变量重复此代码,所以上面的 var1
将更改为 var2
、var3
等。这总是基于相同的 condvar
,尽管对于一半的变量,条件是 df$condvar == 1
。一遍又一遍地重复这一行很麻烦,我想知道是否有更简洁的编码方式。 apply
函数之一会有帮助,还是我需要创建自定义函数?
作为可重现的示例,我希望避免以下代码的重复性:
ex <- mtcars
ex$mpg[ex$vs == 0] <- NA
ex$disp[ex$vs == 0] <- NA
ex$drat[ex$vs == 0] <- NA
ex$cyl[ex$vs == 1] <- NA
ex$hp[ex$vs == 1] <- NA
ex$wt[ex$vs == 1] <- NA
ex
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 NA 6 NA 110 NA 2.620 16.46 0 1 4 4
Mazda RX4 Wag NA 6 NA 110 NA 2.875 17.02 0 1 4 4
Datsun 710 22.8 NA 108.0 NA 3.85 NA 18.61 1 1 4 1
Hornet 4 Drive 21.4 NA 258.0 NA 3.08 NA 19.44 1 0 3 1
Hornet Sportabout NA 8 NA 175 NA 3.440 17.02 0 0 3 2
Valiant 18.1 NA 225.0 NA 2.76 NA 20.22 1 0 3 1
Duster 360 NA 8 NA 245 NA 3.570 15.84 0 0 3 4
etc.
如果有一行代码适用于 condvar == 0
的所有变量,另一行适用于 condvar == 1
.
尝试:
ifelse(df$var1 == 0, NA, df$var1)
这是一个希望不会太复杂的尝试。如果设置要循环的vars
,对应的values
要被选中索引,可以这样:
vars <- c("mpg", "disp", "cyl", "hp")
values <- c(0, 0, 1, 1)
ex[vars] <- Map(function(x,y) replace(x, ex$vs == y, NA), ex[vars], vals)
# mpg cyl disp hp drat wt qsec vs am gear carb
#Mazda RX4 NA 6 NA 110 3.90 2.620 16.46 0 1 4 4
#Mazda RX4 Wag NA 6 NA 110 3.90 2.875 17.02 0 1 4 4
#Datsun 710 22.8 NA 108.0 NA 3.85 2.320 18.61 1 1 4 1
#Hornet 4 Drive 21.4 NA 258.0 NA 3.08 3.215 19.44 1 0 3 1
#Hornet Sportabout NA 8 NA 175 3.15 3.440 17.02 0 0 3 2
#Valiant 18.1 NA 225.0 NA 2.76 3.460 20.22 1 0 3 1
# ...
如果你只有两组,你可以通过评论中提到的@HubertL 和@Phil 的几个赋值来更简单地做到这一点,但是使用 Map
允许你考虑许多变量和许多可能的变量索引值,无需超过 3 行代码。
使用新的实验性 case_when
函数的 dplyr 方法将类似于:
require(dplyr)
ex <- mtcars
ex <- ex %>%
mutate(mpg = case_when(.$vs==0 ~ as.double(NA), TRUE ~ .$mpg)) %>%
mutate(disp = case_when(.$vs==0 ~ as.double(NA), TRUE ~ .$disp)) %>%
mutate(cyl = case_when(.$vs==1 ~ as.double(NA), TRUE ~ .$cyl)) %>%
mutate(hp = case_when(.$vs==1 ~ as.double(NA), TRUE ~ .$hp))
备注:
- Hadley 说 on 2016-06-27 "case_when() is still somewhat experiment and does not currently work inside mutate(). That will be fixed in a future version." 我花了 40 分钟才得到这段代码。你明白了。一旦
case_when
起作用,它就会很好。同时filter()
的解决方法低于 - 您必须使用
.$var
来引用 RHS 上的变量 - 您必须在 RHS 上指定 NA 的类型,因此所有
as.double(NA)
TRUE ~ ...
指定默认子句
使用 filter()
的解决方法:
ex <- rbind(ex %>% filter(vs==0) %>% mutate(mpg=NA, disp=NA),
ex %>% filter(vs==1) %>% mutate(cyl=NA, hp=NA) )
由于 vs
感谢@HubertL(欢迎post回答这个问题,我会投赞成票)和@smci:
ex[ex$vs == 0, c("mpg", "disp", ...)] <- NA
ex[ex$vs == 1, c("cyl", "hp", ...)] <- NA