选择大范围的值在 R 中重新编码
Selecting a large range of values to recode in R
我想跨多个列重新编码大量变量。这是一个例子 df
df <- data.frame(
id_number = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
age = c(10, 11, 12, 13, 14, 15, 16, 17, 18, 19),
abc1 = c(501, 502, 503, 504, 505, 506, 507, 508, 509, 510),
abc2 = c(501, 502, 501, 501, 502, 501, 502, 503, 501, 502),
abc3 = c(501, 506, 501, 501, 510, 501, 510, 501, 501, 501),
abc4 = c(507, 505, 501, 501, 501, 501, 501, 501, 501, 501)
)
df
列 abc1:abc4 的值为 501:510,我正在尝试同时将所有这些列中的 501:508 重新编码为 91、509 为 92 和 510 为 93。
这是我试过的 -
library(dplyr)
df1 <-
df %>%
mutate(across(
abc1:abc4,
~ recode(
.x,
`501:508` = 91L,
`509` = 92L,
`510` = 93L
)
))
但是我得到一个错误
x 强制引入的 NA
ℹ 输入 ..1
是 across(abc1:abc4, ~recode(.x, `501:508` = 91L, `509` = 92L, `510` = 93L))
.NAs 由带有 mutate()
输入 ..1
的强制问题引入。
x 未替换的值被视为 NA,因为 .x 不兼容。请详细说明替换或提供 .default
但是,如果我一个一个地更改值,它会起作用,但我想一次全部完成,因为我的真实数据有一个很长的值列表。我是不是做错了什么
`501:508` = 91L,
谢谢!
上面的后续问题
假设 abc1:abc4 的值更大,并且还有一组范围为 1-175 的附加值。
abc1:abc4 = c(1:175, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510)。我只是调整了我之前示例中的值以在此处说明这一点。
df1 <- data.frame(
id_number = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
age = c(10, 11, 12, 13, 14, 15, 16, 17, 18, 19),
abc1 = c(14, 158, 170, 504, 505, 506, 507, 508, 509, 510),
abc2 = c(501, 502, 501, 501, 45, 501, 502, 59, 501, 100),
abc3 = c(89, 506, 12, 501, 510, 13, 510, 501, 11, 501),
abc4 = c(32, 505, 35, 501, 501, 56, 501, 12, 501, 501)
)
df1
现在我想将它们全部一起重新编码,其中 1:175 = 90、501:508 = 91、509 = 92 和 510 - 93 跨 abc1:abc4 列一次。 @akrun 的答案中的“nm1”将如何在此处设置。有没有更简单的方法来做到这一点?谢谢!
一个更简单的选择是匹配命名向量
library(dplyr)
nm1 <- setNames(rep(c(91, 92, 93), c(8, 1, 1)), 501:510)
df1 <- df %>%
mutate(across(abc1:abc4, ~ nm1[as.character(.x)]))
-输出
df1
id_number age abc1 abc2 abc3 abc4
1 1 10 91 91 91 91
2 2 11 91 91 91 91
3 3 12 91 91 91 91
4 4 13 91 91 91 91
5 5 14 91 91 93 91
6 6 15 91 91 91 91
7 7 16 91 91 93 91
8 8 17 91 91 91 91
9 9 18 92 91 91 91
10 10 19 93 91 91 91
命名向量的使用也适用于 recode
df %>%
mutate(across(abc1:abc4, ~ recode(., !!! nm1)))
-输出
id_number age abc1 abc2 abc3 abc4
1 1 10 91 91 91 91
2 2 11 91 91 91 91
3 3 12 91 91 91 91
4 4 13 91 91 91 91
5 5 14 91 91 93 91
6 6 15 91 91 91 91
7 7 16 91 91 93 91
8 8 17 91 91 91 91
9 9 18 92 91 91 91
10 10 19 93 91 91 91
对于更新的案例,我们可以使用 rep
扩展命名向量
nm2 <- setNames(rep(c(90, 91, 92, 93), c(175, 8, 1, 1)), c(1:175, 501:510))
df1 %>%
mutate(across(abc1:abc4, ~ nm2[as.character(.x)]))
id_number age abc1 abc2 abc3 abc4
1 1 10 90 91 90 90
2 2 11 90 91 91 91
3 3 12 90 91 90 90
4 4 13 91 91 91 91
5 5 14 91 90 93 91
6 6 15 91 91 90 90
7 7 16 91 91 93 91
8 8 17 91 90 91 90
9 9 18 92 91 90 91
10 10 19 93 90 91 91
或使用相同的向量,然后使用 case_when
创建条件
df1 %>%
mutate(across(abc1:abc4, ~ case_when(. %in% 1:175 ~ 90,
TRUE ~ nm1[as.character(.)])))
id_number age abc1 abc2 abc3 abc4
1 1 10 90 91 90 90
2 2 11 90 91 91 91
3 3 12 90 91 90 90
4 4 13 91 91 91 91
5 5 14 91 90 93 91
6 6 15 91 91 90 90
7 7 16 91 91 93 91
8 8 17 91 90 91 90
9 9 18 92 91 90 91
10 10 19 93 90 91 91
另一个dplyr
选项
> df %>%
+ mutate(across(abc1:abc4, ~ 90 + as.integer(cut(., c(500, 508, 509, 510)))))
id_number age abc1 abc2 abc3 abc4
1 1 10 91 91 91 91
2 2 11 91 91 91 91
3 3 12 91 91 91 91
4 4 13 91 91 91 91
5 5 14 91 91 93 91
6 6 15 91 91 91 91
7 7 16 91 91 93 91
8 8 17 91 91 91 91
9 9 18 92 91 91 91
10 10 19 93 91 91 91
遵循与上述类似想法的基础 R 选项
idx <- startsWith(names(df), "abc")
df[idx] <- 90 + as.integer(cut(unlist(df[idx]), c(500, 508, 509, 510)))
给予
> df
id_number age abc1 abc2 abc3 abc4
1 1 10 91 91 91 91
2 2 11 91 91 91 91
3 3 12 91 91 91 91
4 4 13 91 91 91 91
5 5 14 91 91 93 91
6 6 15 91 91 91 91
7 7 16 91 91 93 91
8 8 17 91 91 91 91
9 9 18 92 91 91 91
10 10 19 93 91 91 91
我想跨多个列重新编码大量变量。这是一个例子 df
df <- data.frame(
id_number = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
age = c(10, 11, 12, 13, 14, 15, 16, 17, 18, 19),
abc1 = c(501, 502, 503, 504, 505, 506, 507, 508, 509, 510),
abc2 = c(501, 502, 501, 501, 502, 501, 502, 503, 501, 502),
abc3 = c(501, 506, 501, 501, 510, 501, 510, 501, 501, 501),
abc4 = c(507, 505, 501, 501, 501, 501, 501, 501, 501, 501)
)
df
列 abc1:abc4 的值为 501:510,我正在尝试同时将所有这些列中的 501:508 重新编码为 91、509 为 92 和 510 为 93。 这是我试过的 -
library(dplyr)
df1 <-
df %>%
mutate(across(
abc1:abc4,
~ recode(
.x,
`501:508` = 91L,
`509` = 92L,
`510` = 93L
)
))
但是我得到一个错误
x 强制引入的 NA
ℹ 输入 ..1
是 across(abc1:abc4, ~recode(.x, `501:508` = 91L, `509` = 92L, `510` = 93L))
.NAs 由带有 mutate()
输入 ..1
的强制问题引入。
x 未替换的值被视为 NA,因为 .x 不兼容。请详细说明替换或提供 .default
但是,如果我一个一个地更改值,它会起作用,但我想一次全部完成,因为我的真实数据有一个很长的值列表。我是不是做错了什么
`501:508` = 91L,
谢谢!
上面的后续问题
假设 abc1:abc4 的值更大,并且还有一组范围为 1-175 的附加值。 abc1:abc4 = c(1:175, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510)。我只是调整了我之前示例中的值以在此处说明这一点。
df1 <- data.frame(
id_number = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
age = c(10, 11, 12, 13, 14, 15, 16, 17, 18, 19),
abc1 = c(14, 158, 170, 504, 505, 506, 507, 508, 509, 510),
abc2 = c(501, 502, 501, 501, 45, 501, 502, 59, 501, 100),
abc3 = c(89, 506, 12, 501, 510, 13, 510, 501, 11, 501),
abc4 = c(32, 505, 35, 501, 501, 56, 501, 12, 501, 501)
)
df1
现在我想将它们全部一起重新编码,其中 1:175 = 90、501:508 = 91、509 = 92 和 510 - 93 跨 abc1:abc4 列一次。 @akrun 的答案中的“nm1”将如何在此处设置。有没有更简单的方法来做到这一点?谢谢!
一个更简单的选择是匹配命名向量
library(dplyr)
nm1 <- setNames(rep(c(91, 92, 93), c(8, 1, 1)), 501:510)
df1 <- df %>%
mutate(across(abc1:abc4, ~ nm1[as.character(.x)]))
-输出
df1
id_number age abc1 abc2 abc3 abc4
1 1 10 91 91 91 91
2 2 11 91 91 91 91
3 3 12 91 91 91 91
4 4 13 91 91 91 91
5 5 14 91 91 93 91
6 6 15 91 91 91 91
7 7 16 91 91 93 91
8 8 17 91 91 91 91
9 9 18 92 91 91 91
10 10 19 93 91 91 91
命名向量的使用也适用于 recode
df %>%
mutate(across(abc1:abc4, ~ recode(., !!! nm1)))
-输出
id_number age abc1 abc2 abc3 abc4
1 1 10 91 91 91 91
2 2 11 91 91 91 91
3 3 12 91 91 91 91
4 4 13 91 91 91 91
5 5 14 91 91 93 91
6 6 15 91 91 91 91
7 7 16 91 91 93 91
8 8 17 91 91 91 91
9 9 18 92 91 91 91
10 10 19 93 91 91 91
对于更新的案例,我们可以使用 rep
nm2 <- setNames(rep(c(90, 91, 92, 93), c(175, 8, 1, 1)), c(1:175, 501:510))
df1 %>%
mutate(across(abc1:abc4, ~ nm2[as.character(.x)]))
id_number age abc1 abc2 abc3 abc4
1 1 10 90 91 90 90
2 2 11 90 91 91 91
3 3 12 90 91 90 90
4 4 13 91 91 91 91
5 5 14 91 90 93 91
6 6 15 91 91 90 90
7 7 16 91 91 93 91
8 8 17 91 90 91 90
9 9 18 92 91 90 91
10 10 19 93 90 91 91
或使用相同的向量,然后使用 case_when
df1 %>%
mutate(across(abc1:abc4, ~ case_when(. %in% 1:175 ~ 90,
TRUE ~ nm1[as.character(.)])))
id_number age abc1 abc2 abc3 abc4
1 1 10 90 91 90 90
2 2 11 90 91 91 91
3 3 12 90 91 90 90
4 4 13 91 91 91 91
5 5 14 91 90 93 91
6 6 15 91 91 90 90
7 7 16 91 91 93 91
8 8 17 91 90 91 90
9 9 18 92 91 90 91
10 10 19 93 90 91 91
另一个dplyr
选项
> df %>%
+ mutate(across(abc1:abc4, ~ 90 + as.integer(cut(., c(500, 508, 509, 510)))))
id_number age abc1 abc2 abc3 abc4
1 1 10 91 91 91 91
2 2 11 91 91 91 91
3 3 12 91 91 91 91
4 4 13 91 91 91 91
5 5 14 91 91 93 91
6 6 15 91 91 91 91
7 7 16 91 91 93 91
8 8 17 91 91 91 91
9 9 18 92 91 91 91
10 10 19 93 91 91 91
遵循与上述类似想法的基础 R 选项
idx <- startsWith(names(df), "abc")
df[idx] <- 90 + as.integer(cut(unlist(df[idx]), c(500, 508, 509, 510)))
给予
> df
id_number age abc1 abc2 abc3 abc4
1 1 10 91 91 91 91
2 2 11 91 91 91 91
3 3 12 91 91 91 91
4 4 13 91 91 91 91
5 5 14 91 91 93 91
6 6 15 91 91 91 91
7 7 16 91 91 93 91
8 8 17 91 91 91 91
9 9 18 92 91 91 91
10 10 19 93 91 91 91