请考虑以下数据帧列表:
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))
如果还不是这样,我想将A
和B
的元素连接到B
列中。请注意,并非所有数据框都具有B
列。
执行此操作的条件如下:
A
和B
列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
}
)
)
它不起作用。
而且,我没有写第二个条件。我尝试了& setequal(. %>% pull(A), . %>% pull(B) %>% word(1))
,但没有成功。
修改:
我需要单独保留所有数据帧。 B
中仅df1
列应被重写。 df2
,df3
和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
答案 0 :(得分:5)
您可以首先检查A和B是否在列中,如果是,则检查第一个元素(str_sub(B, 1, 1)
)是否与A不匹配,如果是,则将A和B组合在一起
使用@Moody_Mudskipper建议的map_if
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)))
更详细:
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
答案 1 :(得分:1)
我不确定我是否理解您的问题,但是可以尝试回答以下问题:
bind_rows(df_ls) %>% #create on tibble with all data.frames
select(id, A, B) %>% #select relevant columns
filter_at(vars("A", "B"), all_vars(!is.na(.))) %>% #keep only those rows which have columns A and B (condition 1)
mutate(B = if_else(str_extract(A, "^.") != str_extract(B, "^."), paste(A, B), B)) #if the first letter of B is the same as the first letter in A then keep B otherwise paste A and B together (condition 2)
# A tibble: 8 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
6 1 A A j
7 2 B B k
8 3 C C l
在发布所需的结果后,可以在此处保留列表:
myfun <- function(df){
if ("A" %in% colnames(df) & "B" %in% colnames(df)) {
mutate(df, B = if_else(str_extract(A, "^.") != str_extract(B, "^."), paste(A, B), B))
} else df
}
df_ls %>% map(myfun)