r - R用if语句改变多列
问题描述
我有这样的数据:
cols <- c("X01_01","X01_01_p", "X01_02","X01_02_p", "X01_03","X01_03_p", "X01_04", "X01_05","X01_06")
set.seed(111)
values <- replicate(9, sample(1:5, 4, replace = TRUE))
df <- as.data.frame(values)
所以我的 df 看起来像这样:
X01_01 X01_01_p X01_02 X01_02_p X01_03 X01_03_p X01_04 X01_05 X01_06
1 3 2 3 1 1 3 5 4 3
2 4 3 1 1 5 2 2 3 3
3 2 1 3 1 2 2 4 1 2
4 3 3 3 3 4 2 2 3 4
我有一些列用于突变(不是全部)和新列的名称。
cols_to_mutate <- c("X01_01_p","X01_02_p", "X01_03_p", "X01_04", "X01_05","X01_06")
new_cols <- c("X01_01_n","X01_02_n", "X01_03_n", "X01_04_n", "X01_05_n","X01_06_n")
每个突变都是相同的:
- 如果值为 1 或 2,则新值必须为 0
- 如果值为 3,则新值必须为 0.5
- 如果值为 4 或 5,则新值必须为 1
最终我的 df 看起来像这样:
X01_01 X01_01_p X01_02 X01_02_p X01_03 X01_03_p X01_04 X01_05 X01_06 X01_01_n X01_02_n X01_03_n X01_04_n X01_05_n X01_06_n
1 3 2 3 1 1 3 5 4 3 0.0 0.0 0.5 1 1.0 0.5
2 4 3 1 1 5 2 2 3 3 0.5 0.0 0.0 0 0.5 0.5
3 2 1 3 1 2 2 4 1 2 0.0 0.0 0.0 1 0.0 0.0
4 3 3 3 3 4 2 2 3 4 0.5 0.5 0.0 0 0.5 1.0
在“硬编码”中,我可以写很多这样的行:
df <- mutate(df, X01_01_n = ifelse(X01_01_p <= 2, 0, (ifelse(X01_01_p == 3, 0.5, 1))))
df <- mutate(df, X01_02_n = ifelse(X01_02_p <= 2, 0, (ifelse(X01_02_p == 3, 0.5, 1))))
但当然我正在寻找一种更花哨和更快的方法来做到这一点,但我搜索了又搜索,但没有找到解决方案。我试过了:
df <- cbind(df,apply(df[,cols_to_mutate],2, function(x) if (x < 3) { 0} else if (x > 3) {1} else {.5}))
但这不起作用。任何想法都会很棒!
解决方案
如果保留先前的列而不是在适当的位置进行变异并不重要,则可以在用于变异的函数内部使用mutate_at
a 。case_when
case_when
使用between
函数 fromdplyr
设置条件,然后用 赋值~
。最后一个参数 ,T ~ NA_real_
分配NA
给不符合任何条件的任何观察。
library(tidyverse)
cols_to_mutate <- c("X01_01_p","X01_02_p", "X01_03_p", "X01_04", "X01_05","X01_06")
df %>%
mutate_at(cols_to_mutate, function(x) {
case_when(
between(x, 1, 2) ~ 0,
x == 3 ~ 0.5,
between(x, 4, 5) ~ 1,
T ~ NA_real_
)
})
#> X01_01 X01_01_p X01_02 X01_02_p X01_03 X01_03_p X01_04 X01_05 X01_06
#> 1 3 0.0 3 0.0 1 0.5 1 1.0 0.5
#> 2 4 0.5 1 0.0 5 0.0 0 0.5 0.5
#> 3 2 0.0 3 0.0 2 0.0 1 0.0 0.0
#> 4 3 0.5 3 0.5 4 0.0 0 0.5 1.0
如果有必要保留原始列并为重新调整的列赋予新名称,这里有一些rlang
+purrr
技巧。我所做的是imap
编辑数据框的列。如果名称在要变异的列列表中,我使用与case_when
上面相同的方法,并输出tibble
带有两列的 a:一是原始列,其名称使用quo_name
和:=
运算符分配,另一列是新的值列,具有相同的名称但_n
附加。如果它不是要变异的列,它只会返回tibble
原始列的 a。通过使用imap_dfc
,所有列都重新绑定到一个数据帧中。
df %>%
imap_dfc(function(x, name) {
if (name %in% cols_to_mutate) {
new_vals <- case_when(
between(x, 1, 2) ~ 0,
x == 3 ~ 0.5,
between(x, 4, 5) ~ 1,
T ~ NA_real_
)
tibble(!!quo_name(name) := x, !!quo_name(paste0(name, "_n")) := new_vals)
} else {
tibble(!!quo_name(name) := x)
}
})
#> # A tibble: 4 x 15
#> X01_01 X01_01_p X01_01_p_n X01_02 X01_02_p X01_02_p_n X01_03 X01_03_p
#> <int> <int> <dbl> <int> <int> <dbl> <int> <int>
#> 1 3 2 0 3 1 0 1 3
#> 2 4 3 0.5 1 1 0 5 2
#> 3 2 1 0 3 1 0 2 2
#> 4 3 3 0.5 3 3 0.5 4 2
#> # ... with 7 more variables: X01_03_p_n <dbl>, X01_04 <int>,
#> # X01_04_n <dbl>, X01_05 <int>, X01_05_n <dbl>, X01_06 <int>,
#> # X01_06_n <dbl>
推荐阅读
- html - 轮播无法将图像 div 移到中心
- java - 如何在独立的命令行应用程序(jar-with-dependencies)中关闭所有日志记录(即使是依赖项)
- excel - 确定受保护的视图选项在文档中是否处于活动状态
- mysql - 将 clearDB 数据库备份到本地
- android - 当手机不充电时,BluetoothGatt.Connect 不工作
- jquery - 如何在 jQuery 中使用 FormData() 成功提交表单后重定向
- asp.net - xeri-api aspx vb.net 如何断开连接的公司
- sorting - 如何根据参数对 terraform 中的数据源进行排序
- php - Laravel 通知存储附加 ID 字段
- java - 有效括号 Java