我有一个示例数据集,其中一列的内容如下所示:
Candy Sanitizer Candy Water Cake Candy Ice Cream Gum Candy Coffee
我想做的是把它替换成两个因子--“Candy”和“Non-Candy”。我可以用Python/Pandas来做这件事,但似乎找不到基于dplyr的解决方案。谢谢!
fjaof16o1#
在dplyr和tidyr中
dplyr
tidyr
dat %>% mutate(var = replace(var, var != "Candy", "Not Candy"))
明显比ifelse方法快。创建初始 Dataframe 的代码如下所示:
ifelse
library(dplyr) dat <- as_data_frame(c("Candy","Sanitizer","Candy","Water","Cake","Candy","Ice Cream","Gum","Candy","Coffee")) colnames(dat) <- "var"
h9vpoimq2#
假设数据框为dat,列为var:
dat
var
dat = dat %>% mutate(candy.flag = factor(ifelse(var == "Candy", "Candy", "Non-Candy")))
sulc1iza3#
dplyr使用case_when的另一个解决方案:
case_when
dat %>% mutate(var = case_when(var == 'Candy' ~ 'Candy', TRUE ~ 'Non-Candy'))
case_when的语法是condition ~ value to replace。文档here。可能比使用replace的解决方案效率更低,但优点是可以在单个命令中执行多个替换,同时仍然具有良好的可读性,即替换以产生三个级别:
condition ~ value to replace
replace
dat %>% mutate(var = case_when(var == 'Candy' ~ 'Candy', var == 'Water' ~ 'Water', TRUE ~ 'Neither-Water-Nor-Candy'))
ux6nzvsh4#
不需要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)要"高效得多“:
?levels
library(microbenchmark) set.seed(01239) # resample data smp <- data.frame(sample(dat$var, 1e6, TRUE)) names(smp) <- "var" timings <- replicate(50, { # copy data to facilitate reuse cop <- smp t0 <- get_nanotime() levs <- setdiff(levels(cop$var), "Candy") levels(cop$var) <- list(Candy = "Candy", "Non-Candy" = levs) t1 <- get_nanotime() - t0 cop <- smp t0 <- get_nanotime() cop = cop %>% mutate(candy.flag = factor(ifelse(var == "Candy", "Candy", "Non-Candy"))) t2 <- get_nanotime() - t0 cop <- smp t0 <- get_nanotime() cop$var <- factor(cop$var == "Candy", labels = c("Non-Candy", "Candy")) t3 <- get_nanotime() - t0 c(levels = t1, dplyr = t2, direct = t3) }) x <- apply(times, 1, median) x[2]/x[1] # dplyr direct # 8.894303 4.962791
也就是说,这是9倍快。
new9mtju5#
我没有对此进行基准测试,但至少在某些情况下,如果有多个条件,mutate 和list的组合似乎提供了一个简单的解决方案:
# assuming that all sweet things fall in one category dat <- data.frame(var = c("Candy", "Sanitizer", "Candy", "Water", "Cake", "Candy", "Ice Cream", "Gum", "Candy", "Coffee")) conditions <- list("Candy" = TRUE, "Sanitizer" = FALSE, "Water" = FALSE, "Cake" = TRUE, "Ice Cream" = TRUE, "Gum" = TRUE, "Coffee" = FALSE) dat %>% mutate(sweet = conditions[var])
jhiyze9q6#
当你只需要两个值时,我认为简单的ifelse()是很好的。而且,嵌入式ifelses可以模拟与PhJ提出的case_when解决方案相同的情况(虽然我确实喜欢他的可读性)!
dat %>% mutate( var = ifelse(var == "Candy", "Candy", "Non-Candy") )
vwoqyblh7#
较新的解决方案是从dplyr使用case_match
case_match
library(dplyr) dat %>% mutate(var = case_match(var, "Candy" ~ var, .default ~ "Not Candy"))
7条答案
按热度按时间fjaof16o1#
在
dplyr
和tidyr
中明显比
ifelse
方法快。创建初始 Dataframe 的代码如下所示:h9vpoimq2#
假设数据框为
dat
,列为var
:sulc1iza3#
dplyr
使用case_when
的另一个解决方案:case_when
的语法是condition ~ value to replace
。文档here。可能比使用
replace
的解决方案效率更低,但优点是可以在单个命令中执行多个替换,同时仍然具有良好的可读性,即替换以产生三个级别:ux6nzvsh4#
不需要
dplyr
。假设var
已经存储为因子:参见
?levels
。这比
ifelse
方法(即bound to be slow)要"高效得多“:也就是说,这是9倍快。
new9mtju5#
我没有对此进行基准测试,但至少在某些情况下,如果有多个条件,mutate 和list的组合似乎提供了一个简单的解决方案:
jhiyze9q6#
当你只需要两个值时,我认为简单的ifelse()是很好的。
而且,嵌入式ifelses可以模拟与PhJ提出的case_when解决方案相同的情况(虽然我确实喜欢他的可读性)!
vwoqyblh7#
较新的解决方案是从
dplyr
使用case_match