Purrr-有条件地突变数据帧列表中的一列

Jun*_*tar 1 r list dplyr purrr

考虑以下数据帧列表:

library(tidyverse)

df1 <- tibble(
  id = 1:5,
  A = LETTERS[1:5],
  B = letters[10:14]
)
df2 <- tibble(
  id = 1:3,
  A = LETTERS[1:3],
  B = paste(LETTERS[1:3], letters[10:12])
)
df3 <- tibble(
  id = 1:6,
  B = paste(LETTERS[1:6], letters[10:15])
)
df4 <- tibble(
  id = 1:4,
  C = paste(LETTERS[15:18], letters[20:23])
)

df_ls <- list(df1, df2, df3, df4) %>% 
  set_names(paste0("df", 1:4))
Run Code Online (Sandbox Code Playgroud)

我想拼接的元素ABB列如果这不是已经是这样了。请注意,并非所有数据框都有一B列。

执行此操作的条件如下:

  1. 数据框必须同时具有AB
  2. 中的第一个字母B必须与的不同A

我正在使用map功能。到目前为止,我的尝试(没有“条件2”):

df_ls %>% 
  map(
    ~ .x %>% 
      mutate_at(
        vars(matches("B")),
        ~ {
          if (c("A", "B") %in% colnames(.) %>% sum() == 2)
            paste(A, B)
          else
            B
        }
      )
  )
Run Code Online (Sandbox Code Playgroud)

没用

另外,我没有写第二个条件。我尝试了& setequal(. %>% pull(A), . %>% pull(B) %>% word(1)),但没有成功。

编辑:
我需要单独保留所有数据帧。仅应重写其中的Bdf1df2df3并且df4应保持不变。
预期的输出是:

$df1
# A tibble: 5 x 3
   id A     B
<int> <chr> <chr>
1     1 A     A j
2     2 B     B k
3     3 C     C l
4     4 D     D m
5     5 E     E n   

$df2
# A tibble: 3 x 3
     id A     B    
  <int> <chr> <chr>
1     1 A     A j  
2     2 B     B k  
3     3 C     C l  

$df3
# A tibble: 6 x 2
     id B    
  <int> <chr>
1     1 A j  
2     2 B k  
3     3 C l  
4     4 D m  
5     5 E n  
6     6 F o  

$df4
# A tibble: 4 x 2
     id C    
  <int> <chr>
1     1 O t  
2     2 P u  
3     3 Q v  
4     4 R w  
Run Code Online (Sandbox Code Playgroud)

kat*_*ath 5

您可以先检查A和B是否在列名中,如果是,则检查第一个元素(str_sub(B, 1, 1))是否不匹配A,如果是,则将A和B合并

随着map_if由@Moody_Mudskipper的建议

df_ls %>% 
  map_if(~ all(c("A", "B") %in% colnames(.x)), 
         ~ mutate(.x, B = if_else(str_sub(B, 1, 1) != A, paste(A, B), B)))
Run Code Online (Sandbox Code Playgroud)

更详细:

df_ls %>% 
  map(~ {if (all(c("A", "B") %in% colnames(.x))) {
   .x %>% 
      mutate(B = if_else(str_sub(B, 1, 1) != A, paste(A, B), B))
  } else {
    .x
  }})

# $df1
# # A tibble: 5 x 3
#      id A     B    
#   <int> <chr> <chr>
# 1     1 A     A j  
# 2     2 B     B k  
# 3     3 C     C l  
# 4     4 D     D m  
# 5     5 E     E n  
# 
# $df2
# # A tibble: 3 x 3
#      id A     B    
#   <int> <chr> <chr>
# 1     1 A     A j  
# 2     2 B     B k  
# 3     3 C     C l  
# 
# $df3
# # A tibble: 6 x 2
#      id B    
#   <int> <chr>
# 1     1 A j  
# 2     2 B k  
# 3     3 C l  
# 4     4 D m  
# 5     5 E n  
# 6     6 F o  
# 
# $df4
# # A tibble: 4 x 2
#      id C    
#   <int> <chr>
# 1     1 O t  
# 2     2 P u  
# 3     3 Q v  
# 4     4 R w
Run Code Online (Sandbox Code Playgroud)

  • 我建议使用`map_if`稍微简化您的解决方案 (4认同)