R 类似于SQL的条件更新
我有以下数据帧R 类似于SQL的条件更新,r,dplyr,data.table,R,Dplyr,Data.table,我有以下数据帧 library(tidyverse) x <- c(1,2,3,NA,NA,4,5) y <- c(1,2,3,5,5,4,5) z <- c(1,1,1,6,7,7,8) df <- data.frame(x,y,z) df x y z 1 1 1 1 2 2 2 1 3 3 3 1 4 NA 5 6 5 NA 5 7 6 4 4 7 7 5 5 8 但是,我必须为x和y变异函数添加if_else语句。这有可能使我的代码变得复杂和难以
library(tidyverse)
x <- c(1,2,3,NA,NA,4,5)
y <- c(1,2,3,5,5,4,5)
z <- c(1,1,1,6,7,7,8)
df <- data.frame(x,y,z)
df
x y z
1 1 1 1
2 2 2 1
3 3 3 1
4 NA 5 6
5 NA 5 7
6 4 4 7
7 5 5 8
但是,我必须为x和y变异函数添加if_else语句。这有可能使我的代码变得复杂和难以阅读。要给你一个SQL类比,考虑下面的代码
UPDATE df
SET x= 1, y= 2
WHERE z = 1;
我希望实现以下目标:
- 提前指定更新条件,这样我就不必为每个mutate函数重复它
- 我希望避免使用data.table或base R。我使用的是dplyr,因此我希望坚持使用它以保持一致性
- 这里有一个带有
map2
的选项。循环遍历数据集的“x”、“y”列以及要更改的值,如果为真,则基于“z”的值应用case_
,然后返回新值,或者返回相同的列并bind
将列与原始数据集绑定
library(dplyr)
library(purrr)
map2_df(df %>%
select(x, y), c(1, 2), ~ case_when(df$z == 1 ~ .y, TRUE ~ .x)) %>%
bind_cols(df %>%
select(z), .) %>%
select(names(df))
或者使用
base R
,创建一个逻辑向量,使用该向量对列“x”、“y”的行进行子集,并通过指定值的列表进行更新
i1 <- df$z == 1
df[i1, c('x', 'y')] <- list(1, 2)
df
# x y z
#1 1 2 1
#2 1 2 1
#3 1 2 1
#4 NA 5 6
#5 NA 5 7
#6 4 4 7
#7 5 5 8
i1
在R底
transform(df,
x = replace(x, z == 1, 1),
y = replace(y, z == 1, 2))
如果将条件存储在变量中,则无需多次键入
condn = (df$z == 1)
transform(df,
x = replace(x, condn, 1),
y = replace(y, condn, 2))
如果您有SQL背景,您应该真正了解:
库(data.table)
dt使用发布在上的mutate_cond
我们可以做到这一点:
df %>% mutate_cond(z == 1, x = 1, y = 2)
给予:
x y z
1 1 2 1
2 1 2 1
3 1 2 1
4 NA 5 6
5 NA 5 7
6 4 4 7
7 5 5 8
sqldf
当然,您可以使用sqldf直接在SQL中实现它——忽略后端RSQLite发出的警告消息
library(sqldf)
sqldf(c("update df set x = 1, y = 2 where z = 1", "select * from df"))
基尔
它在R底笔直向前:
df[df$z == 1, c("x", "y")] <- list(1, 2)
df[df$z==1,c(“x”,“y”)]谢谢你介绍我变异条件。我真的希望它包含在dplyr中!!
df %>% mutate_cond(z == 1, x = 1, y = 2)
x y z
1 1 2 1
2 1 2 1
3 1 2 1
4 NA 5 6
5 NA 5 7
6 4 4 7
7 5 5 8
library(sqldf)
sqldf(c("update df set x = 1, y = 2 where z = 1", "select * from df"))
df[df$z == 1, c("x", "y")] <- list(1, 2)