#r #database #dataframe #collapse
#r #База данных #фрейм данных
Вопрос:
У меня есть два столбца, которые я хочу свернуть, если они разные. Если они одинаковые, просто сохраните значение. Если есть один 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
Ответ №1:
Попробуйте этот подход с 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
Комментарии:
1. Хорошая утка, лаконичная и быстрая еще раз.
2. Утка, я вижу без аргумента пробела, в первой строке после A стоит запятая. Он заменяет ‘,’ пробелом, а затем trimws удаляет его?
Ответ №2:
Работает ли это:
> df %>% mutate(element3 = case_when(
There were 14 warnings (use warnings() to see them)
element1 == element2 ~ element1,
is.na(element1) amp; !is.na(element2) ~ element2,
is.na(element2) amp; !is.na(element1) ~ element1,
element1 == '' amp; element2 != '' ~ element2,
element1 != '' amp; 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
>
Ответ №3:
Вот еще 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
Ответ №4:
В 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"