我有一个示例数据集,其列的读取方式如下:
Candy
Sanitizer
Candy
Water
Cake
Candy
Ice Cream
Gum
Candy
Coffee
我想做的是将其替换为两个因素 - “糖果”和“非糖果”。我可以用Python / Pandas做到这一点,但似乎无法弄清楚基于dplyr的解决方案。谢谢!
答案 0 :(得分:21)
dplyr
和tidyr
dat %>%
mutate(var = replace(var, var != "Candy", "Not Candy"))
明显快于ifelse
方法。
创建初始数据库的代码如下:
library(dplyr)
dat <- as_data_frame(c("Candy","Sanitizer","Candy","Water","Cake","Candy","Ice Cream","Gum","Candy","Coffee"))
colnames(dat) <- "var"
答案 1 :(得分:6)
假设您的数据框为dat
且您的专栏为var
:
dat = dat %>% mutate(candy.flag = factor(ifelse(var == "Candy", "Candy", "Non-Candy")))
答案 2 :(得分:6)
无需dplyr
。假设var
已存储为因素:
non_c <- setdiff(levels(dat$var), "Candy")
levels(dat$var) <- list(Candy = "Candy", "Non-Candy" = non_c)
请参阅?levels
。
比ifelse
方法更有效率,bound to be slow:
library(microbenchmark)
set.seed(01239)
smp <- data.frame(sample(dat$var, 1e6, TRUE))
names(smp) <- "var"
times <-
replicate(50,
{cop <- smp
s <- get_nanotime()
levs <- setdiff(levels(cop$var), "Candy")
levels(cop$var) <- list(Candy = "Candy", "Non-Candy" = levs)
d1 <- get_nanotime() - s
cop <- smp
s <- get_nanotime()
cop = cop %>%
mutate(candy.flag = factor(ifelse(var == "Candy",
"Candy", "Non-Candy")))
d2 <- get_nanotime() - s
cop <- smp
s <- get_nanotime()
cop$var <-
factor(cop$var == "Candy", labels = c("Non-Candy", "Candy"))
d3 <- get_nanotime() - s
c(levels = d1, dplyr = d2, direct = d3)})
(x <- apply(times, 1, median))[2]/x[1]
# dplyr direct
# 8.894303 4.962791
也就是说,这快9倍。
答案 3 :(得分:4)
使用dplyr
和case_when
的另一种解决方案:
dat %>%
mutate(var = case_when(var == 'Candy' ~ 'Candy',
TRUE ~ 'Non-Candy'))
case_when
的语法为condition ~ value to replace
。文档here。
可能比使用replace
的解决方案效率低,但是一个优点是可以在单个命令中执行多次替换,同时仍保持良好的可读性,即替换以产生三个级别:
dat %>%
mutate(var = case_when(var == 'Candy' ~ 'Candy',
var == 'Water' ~ 'Water',
TRUE ~ 'Neither-Water-Nor-Candy'))
答案 4 :(得分:0)
我认为,当您只需要两个值时,一个简单的ifelse()很简单。
此外,嵌入式ifelses可以模拟与PhJ提出的case_when解决方案相同的情况(不过,我确实喜欢他的可读性)!
dat %>%
mutate(
var = ifelse(var == "Candy", "Candy", "Non-Candy")
)