R语言 有没有办法将多个列中的值转换为列名?

aor9mmx1  于 2023-04-09  发布在  其他
关注(0)|答案(3)|浏览(187)

我有一个dataframe:

df <- structure(list(ziekten = c(1, 2, 2, 2, 2, 2, 1, 2, 2, 2), voedselallergie = c("no", 
"no", "no", "no", "no", "no", "no", "no", "no", "no"), ziekaller2 = c("no", 
"no", "no", "no", "no", "no", "no", "no", "no", "no"), hooikoorts = c("yes", 
"no", "no", "no", "no", "no", "yes", "no", "no", "no"), ziekaller4 = c("no", 
"no", "no", "no", "no", "no", "no", "no", "no", "no"), ziekaller5 = c("no", 
"no", "no", "no", "no", "no", "no", "no", "no", "no"), anderallergie = c("no", 
"no", "no", "no", "no", "no", "no", "no", "no", "no"), astma = c("no", 
"no", "no", "no", "no", "no", "no", "no", "no", "no"), ziekdiabet1 = c("no", 
"no", "no", "no", "no", "no", "no", "no", "no", "no")), row.names = c(NA, 
-10L), class = c("tbl_df", "tbl", "data.frame"))

这只是我在实际 Dataframe 中拥有的列总数的一小部分,但我想将列中的值更改为相应的列名。我知道如何使用ifelsecase_when来完成,但这并不有效。
第一列可以保持原样,所以从第二列开始,我想将值'yes'更改为列名。这将是结果:

df_new <-  structure(list(ziekten = c(1, 2, 2, 2, 2, 2, 1, 2, 2, 2), voedselallergie = c(NA, 
    NA, NA, NA, NA, NA, NA, NA, NA, NA), ziekaller2 = c(NA, NA, NA, 
    NA, NA, NA, NA, NA, NA, NA), hooikoorts = c("hooikoorts", NA, 
    NA, NA, NA, NA, "hooikoorts", NA, NA, NA), ziekaller4 = c(NA, 
    NA, NA, NA, NA, NA, NA, NA, NA, NA), ziekaller5 = c(NA, NA, NA, 
    NA, NA, NA, NA, NA, NA, NA), anderallergie = c(NA, NA, NA, NA, 
    NA, NA, NA, NA, NA, NA), astma = c(NA, NA, NA, NA, NA, NA, NA, 
    NA, NA, NA), ziekdiabet1 = c(NA, NA, NA, NA, NA, NA, NA, NA, 
    NA, NA)), row.names = c(NA, -10L), class = c("tbl_df", "tbl", 
    "data.frame"))

希望能帮到你!

9jyewag0

9jyewag01#

一个衬垫底座R:

df[-1] <- Map(function(nm, x) ifelse(x == "yes", nm, nm[NA]),
              names(df)[-1], df[-1])
df
# # A tibble: 10 × 9
#    ziekten voedselallergie ziekaller2 hooikoorts ziekaller4 ziekaller5 anderallergie astma ziekdiabet1
#      <dbl> <chr>           <chr>      <chr>      <chr>      <chr>      <chr>         <chr> <chr>      
#  1       1 <NA>            <NA>       hooikoorts <NA>       <NA>       <NA>          <NA>  <NA>       
#  2       2 <NA>            <NA>       <NA>       <NA>       <NA>       <NA>          <NA>  <NA>       
#  3       2 <NA>            <NA>       <NA>       <NA>       <NA>       <NA>          <NA>  <NA>       
#  4       2 <NA>            <NA>       <NA>       <NA>       <NA>       <NA>          <NA>  <NA>       
#  5       2 <NA>            <NA>       <NA>       <NA>       <NA>       <NA>          <NA>  <NA>       
#  6       2 <NA>            <NA>       <NA>       <NA>       <NA>       <NA>          <NA>  <NA>       
#  7       1 <NA>            <NA>       hooikoorts <NA>       <NA>       <NA>          <NA>  <NA>       
#  8       2 <NA>            <NA>       <NA>       <NA>       <NA>       <NA>          <NA>  <NA>       
#  9       2 <NA>            <NA>       <NA>       <NA>       <NA>       <NA>          <NA>  <NA>       
# 10       2 <NA>            <NA>       <NA>       <NA>       <NA>       <NA>          <NA>  <NA>
bogh5gae

bogh5gae2#

我们可以在across中使用cur_column()

library(dplyr) #version >= 1.1.0
df %>%
   mutate(across(-1,  ~case_match(.x, "yes" ~ cur_column(),
                .default = NA_character_)))
  • 输出
# A tibble: 10 × 9
   ziekten voedselallergie ziekaller2 hooikoorts ziekaller4 ziekaller5 anderallergie astma ziekdiabet1
     <dbl> <chr>           <chr>      <chr>      <chr>      <chr>      <chr>         <chr> <chr>      
 1       1 <NA>            <NA>       hooikoorts <NA>       <NA>       <NA>          <NA>  <NA>       
 2       2 <NA>            <NA>       <NA>       <NA>       <NA>       <NA>          <NA>  <NA>       
 3       2 <NA>            <NA>       <NA>       <NA>       <NA>       <NA>          <NA>  <NA>       
 4       2 <NA>            <NA>       <NA>       <NA>       <NA>       <NA>          <NA>  <NA>       
 5       2 <NA>            <NA>       <NA>       <NA>       <NA>       <NA>          <NA>  <NA>       
 6       2 <NA>            <NA>       <NA>       <NA>       <NA>       <NA>          <NA>  <NA>       
 7       1 <NA>            <NA>       hooikoorts <NA>       <NA>       <NA>          <NA>  <NA>       
 8       2 <NA>            <NA>       <NA>       <NA>       <NA>       <NA>          <NA>  <NA>       
 9       2 <NA>            <NA>       <NA>       <NA>       <NA>       <NA>          <NA>  <NA>       
10       2 <NA>            <NA>       <NA>       <NA>       <NA>       <NA>          <NA>  <NA>

或者在base R- one-liner中(第一行只是转换为data.frame),而不使用ifelse或case_when(如OP的帖子中提到的)

out <- as.data.frame(df)
out[-1] <- names(df)[-1][NA^(df[-1] != "yes") * col(df[-1])]
brjng4g3

brjng4g33#

您可以在lapply中使用names

df[-1] <- lapply(names(df)[-1], \(x) c(NA, x)[1L + (df[[x]] == "yes")])

或者使用索引(例如,在名称重复的情况下)。

df[-1] <- lapply(2:ncol(df), \(i) c(NA, names(df)[[i]])[1L + (df[[i]] == "yes")])

基准

library(dplyr)
out <- as.data.frame(df)
bench::mark(check=FALSE,
akrun1 = {x <- df %>%
   mutate(across(-1,  ~case_match(.x, "yes" ~ cur_column(),
                                  .default = NA_character_)))},
akrun2 = {out[-1] <- names(df)[-1][NA^(df[-1] != "yes") * col(df[-1])]},
r2evans = {out[-1] <- Map(function(nm, x) ifelse(x == "yes", nm, nm[NA]),
              names(df)[-1], df[-1])},
GKi1 = {out[-1] <- lapply(names(df)[-1], \(x) c(NA, x)[1L + (df[[x]] == "yes")])},
GKi2 = {out[-1] <- lapply(2:ncol(df), \(i) c(NA, names(df)[[i]])[1L + (df[[i]] == "yes")])}
)
#  expression      min  median itr/s…¹ mem_a…² gc/se…³ n_itr  n_gc total…⁴ result
#  <bch:expr> <bch:tm> <bch:t>   <dbl> <bch:b>   <dbl> <int> <dbl> <bch:t> <list>
#1 akrun1       10.2ms  11.1ms    86.6 14.68KB    8.88    39     4   451ms <NULL>
#2 akrun2      271.6µs 297.4µs  3176.   7.28KB   10.5   1518     5   478ms <NULL>
#3 r2evans     295.6µs 323.9µs  3014.   7.91KB   12.5   1452     6   482ms <NULL>
#4 GKi1        158.2µs 172.6µs  5655.  22.61KB   12.4   2739     6   484ms <NULL>
#5 GKi2        169.8µs 184.2µs  5332.  26.52KB   11.3   2363     5   443ms <NULL>

相关问题