使用 across、starts_with 和 ifelse 语句改变多个变量

问题描述 投票:0回答:1

我有以下数据框。

library(dplyr)
data_test = data.frame(va_te=c("yes", "", "no", "yes"),
           va_ti=c("no", "", "yes", "no"),
           va_ze=c("", "no", "yes", "no"),
           jk_te=c(NA, 545, 876, 987),
           jk_ti=c(876, 567, 908, 432),
           jk_ze=c(987, 988, NA, 234),
           loc=c(345, 898, 444, 321))

> data_test
  va_te va_ti va_ze jk_te jk_ti jk_ze loc
1   yes    no          NA   876   987 345
2                no   545   567   988 898
3    no   yes   yes   876   908    NA 444
4   yes    no    no   987   432   234 321

我想使用两种模式来改变第 6 个变量(每组 3 个相似变量一个:va_ 和 jk_)。

对于第一组“va_”,我使用 across + start with + ifelse。

对于第二组“jk_”我想使用相同的方法,但因为我如果在测试中同时使用jk和va,我不知道如何编写这部分。


data_test_2 = data_test %>%
  mutate(across(starts_with("va_"), 
                            ~ ifelse(.x == "", NA, .x), .names = "{col}")) %>%
  mutate(jk_te = ifelse(va_te != "yes", NA, 
                 ifelse(va_te == "yes" & is.na(jk_te), loc, jk_te))) %>%
  mutate(jk_ti = ifelse(va_ti != "yes", NA, 
                 ifelse(va_ti == "yes" & is.na(jk_ti), loc, jk_ti))) %>%
  mutate(jk_ze = ifelse(va_ze != "yes", NA, 
                 ifelse(va_ze == "yes" & is.na(jk_ze), loc, jk_ze))) 

> data_test_2
  va_te va_ti va_ze jk_te jk_ti jk_ze loc
1   yes    no  <NA>   345    NA    NA 345
2  <NA>  <NA>    no    NA    NA    NA 898
3    no   yes   yes    NA   908   444 444
4   yes    no    no   987    NA    NA 321
r dataframe dplyr mutate across
1个回答
0
投票

最简单的方法是首先将数据转换为长格式,其中一列表示

va_
列,一列表示
jk_
列,一列
suffix
分别表示
te, ti
ze

然后您可以轻松转换

va
jk
,特别是对于后者,您还可以使用相应的
va
列:

library(tidyr)
(data_lng <- data_test %>% 
  mutate(across(-loc, as.character)) %>%  ## make character to put into same column
  pivot_longer(-loc, 
               names_to = c("prefix", "suffix"),
               names_sep  ="_",) %>% 
  pivot_wider(names_from = prefix))

# # A tibble: 12 × 4
#      loc suffix va    jk   
#    <dbl> <chr>  <chr> <chr>
#  1   345 te     "yes" NA   
#  2   345 ti     "no"  876  
#  3   345 ze     ""    987  
#  4   898 te     ""    545  
#  5   898 ti     ""    567  
#  6   898 ze     "no"  988  
#  7   444 te     "no"  876  
#  8   444 ti     "yes" 908  
#  9   444 ze     "yes" NA   
# 10   321 te     "yes" 987  
# 11   321 ti     "no"  432  
# 12   321 ze     "no"  234 

然后你可以像这样改变你的列:

(data_lng_mutated <- data_lng %>% 
  mutate(va = if_else(!nzchar(va), NA_character_, va),
         jk = case_when(coalesce(va, "") != "yes" ~ NA_real_,
                        is.na(jk) ~ loc,
                        TRUE ~ as.numeric(jk))))
# # A tibble: 12 × 4
#      loc suffix va       jk
#    <dbl> <chr>  <chr> <dbl>
#  1   345 te     yes     345
#  2   345 ti     no       NA
#  3   345 ze     NA       NA
#  4   898 te     NA       NA
#  5   898 ti     NA       NA
#  6   898 ze     no       NA
#  7   444 te     no       NA
#  8   444 ti     yes     908
#  9   444 ze     yes     444
# 10   321 te     yes     987
# 11   321 ti     no       NA
# 12   321 ze     no       NA

最后一步是将其转换回宽格式:

  
data_lng_mutated %>% 
  pivot_wider(id_cols = loc, values_from = c("va", "jk"), names_from = suffix) %>% 
  relocate(loc, .after = last_col())

# # A tibble: 4 × 7
#   va_te va_ti va_ze jk_te jk_ti jk_ze   loc
#   <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl>
# 1 yes   no    NA      345    NA    NA   345
# 2 NA    NA    no       NA    NA    NA   898
# 3 no    yes   yes      NA   908   444   444
# 4 yes   no    no      987    NA    NA   321
© www.soinside.com 2019 - 2024. All rights reserved.