如果元素不同,则折叠
If elements are different, collapse
我有两列,如果它们不同,我想折叠它们。如果它们相同,则保留该值。如果有一个NA
,保留另一个
df
# element1 element2
#1 A
#2 B B
#3 C D
#4 A <NA>
我需要以下列:
# element1 element2 element12
#1 A A
#2 B B B
#3 C D C,D
#4 A <NA> A
关于我该怎么做的任何提示?
数据:
df = data.frame(element1 = c("A", "B", "C","A"),
element2 = c("", "B","D", NA));df
用 apply()
试试这个方法:
#Code 1
df$Var <- apply(df[1:2],1,function(x) trimws(paste0(unique(x[!is.na(x)]),collapse = ','),
whitespace = ','))
输出:
element1 element2 Var
1 A A
2 B B B
3 C D C,D
4 A <NA> A
或 dplyr
版本:
library(dplyr)
#Code
df %>% mutate(across(everything(),~as.character(.))) %>%
replace(is.na(.),',') %>%
rowwise() %>%
mutate(Var=trimws(paste0(unique(c_across(element1:element2)),
collapse = ','),whitespace = ',')) %>%
replace(.==',',NA)
输出:
# A tibble: 4 x 3
# Rowwise:
element1 element2 Var
<chr> <chr> <chr>
1 A "" A
2 B "B" B
3 C "D" C,D
4 A NA A
这个有用吗:
> df %>% mutate(element3 = case_when(
There were 14 warnings (use warnings() to see them)
+ element1 == element2 ~ element1,
+ is.na(element1) & !is.na(element2) ~ element2,
+ is.na(element2) & !is.na(element1) ~ element1,
+ element1 == '' & element2 != '' ~ element2,
+ element1 != '' & element2 == '' ~ element1,
+ element1 != element2 ~ paste(element1, element2, sep = ',')
+ ))
element1 element2 element3
1 A A
2 B B B
3 C D C,D
4 A <NA> A
>
这是另一个 tidyverse
选项。
如果你想摆脱烦人的空字符串 ""
并使它们成为 NA
,你可以使用 na_if
.
A case_when
可以连接不同的字符串,使用 coalesce
以防一个或另一个丢失 (NA
)。
如果两者都不是,则两列相同,只需设置为第一个值即可。
library(tidyverse)
df %>%
na_if("") %>%
mutate(element12 = case_when(
element1 != element2 ~ paste(element1, element2, sep = ','),
is.na(element1) | is.na(element2) ~ coalesce(element1, element2),
TRUE ~ element1))
输出
element1 element2 element12
1 A <NA> A
2 B B B
3 C D C,D
4 A <NA> A
在base R
中,我们可以用paste
和sub
来做到这一点
df$elements12 <- gsub("(?<=.)(?=.)", ",", sub("(.)\1+", "\1",
do.call(paste, c(replace(df, is.na(df), ""), sep=""))), perl = TRUE)
-输出
df$element12
#[1] "A" "B" "C,D" "A"
我有两列,如果它们不同,我想折叠它们。如果它们相同,则保留该值。如果有一个NA
,保留另一个
df
# element1 element2
#1 A
#2 B B
#3 C D
#4 A <NA>
我需要以下列:
# element1 element2 element12
#1 A A
#2 B B B
#3 C D C,D
#4 A <NA> A
关于我该怎么做的任何提示?
数据:
df = data.frame(element1 = c("A", "B", "C","A"),
element2 = c("", "B","D", NA));df
用 apply()
试试这个方法:
#Code 1
df$Var <- apply(df[1:2],1,function(x) trimws(paste0(unique(x[!is.na(x)]),collapse = ','),
whitespace = ','))
输出:
element1 element2 Var
1 A A
2 B B B
3 C D C,D
4 A <NA> A
或 dplyr
版本:
library(dplyr)
#Code
df %>% mutate(across(everything(),~as.character(.))) %>%
replace(is.na(.),',') %>%
rowwise() %>%
mutate(Var=trimws(paste0(unique(c_across(element1:element2)),
collapse = ','),whitespace = ',')) %>%
replace(.==',',NA)
输出:
# A tibble: 4 x 3
# Rowwise:
element1 element2 Var
<chr> <chr> <chr>
1 A "" A
2 B "B" B
3 C "D" C,D
4 A NA A
这个有用吗:
> df %>% mutate(element3 = case_when(
There were 14 warnings (use warnings() to see them)
+ element1 == element2 ~ element1,
+ is.na(element1) & !is.na(element2) ~ element2,
+ is.na(element2) & !is.na(element1) ~ element1,
+ element1 == '' & element2 != '' ~ element2,
+ element1 != '' & element2 == '' ~ element1,
+ element1 != element2 ~ paste(element1, element2, sep = ',')
+ ))
element1 element2 element3
1 A A
2 B B B
3 C D C,D
4 A <NA> A
>
这是另一个 tidyverse
选项。
如果你想摆脱烦人的空字符串 ""
并使它们成为 NA
,你可以使用 na_if
.
A case_when
可以连接不同的字符串,使用 coalesce
以防一个或另一个丢失 (NA
)。
如果两者都不是,则两列相同,只需设置为第一个值即可。
library(tidyverse)
df %>%
na_if("") %>%
mutate(element12 = case_when(
element1 != element2 ~ paste(element1, element2, sep = ','),
is.na(element1) | is.na(element2) ~ coalesce(element1, element2),
TRUE ~ element1))
输出
element1 element2 element12
1 A <NA> A
2 B B B
3 C D C,D
4 A <NA> A
在base R
中,我们可以用paste
和sub
df$elements12 <- gsub("(?<=.)(?=.)", ",", sub("(.)\1+", "\1",
do.call(paste, c(replace(df, is.na(df), ""), sep=""))), perl = TRUE)
-输出
df$element12
#[1] "A" "B" "C,D" "A"