Как объединить несколько символьных столбцов в один столбец и удалить NA, не зная номеров столбцов - PullRequest
5 голосов
/ 18 марта 2019

Я хотел бы иметь столбец, который содержит символы других столбцов без NA.Я пробовал paste, str_c и unite, но не смог получить ожидаемый результат.Может быть, я использовал их неправильно.

Реальный случай заключается в том, что я не мог знать номера столбцов заранее, так как каждый набор данных можно варьировать с точки зрения лет.

т.е. некоторые наборы данных содержат 10 лет,но некоторые содержат 20 лет.

Вот входные данные:

input <- tibble(
  id = c('aa', 'ss', 'dd', 'qq'),
  '2017' = c('tv', NA, NA, 'web'),
  '2018' = c(NA, 'web', NA, NA),
  '2019' = c(NA, NA, 'book', 'tv')
)

# A tibble: 4 x 4
  id    `2017` `2018` `2019`
  <chr> <chr>  <chr>  <chr> 
1 aa    tv     NA     NA    
2 ss    NA     web    NA    
3 dd    NA     NA     book  
4 qq    web    NA     tv    

Желаемый результат с колонкой ALL:

> output
# A tibble: 4 x 5
  id    `2017` `2018` `2019` ALL   
  <chr> <chr>  <chr>  <chr>  <chr> 
1 aa    tv     NA     NA     tv    
2 ss    NA     web    NA     web   
3 dd    NA     NA     book   book  
4 qq    web    NA     tv     web tv

Спасибо за помощь!

Ответы [ 4 ]

4 голосов
/ 18 марта 2019

Вот метод base R

input$ALL <- apply(input[-1], 1, function(x) paste(na.omit(x), collapse=" "))
input$ALL
#[1] "tv"     "web"    "book"   "web tv"
4 голосов
/ 18 марта 2019

Это на самом деле дубликат (или очень близко) этого вопроса, но с тех пор все изменилось . unite имеет параметр na.rm, который помогает сбросить NA с.

Что касается выбора столбцов, здесь мы выбрали все столбцы, игнорируя первый, без указания имен столбцов, поэтому он должен работать в вашем случае с несколькими годами.

library(tidyverse)

input %>%
    unite("ALL", names(input)[-1], remove = FALSE, sep = " ", na.rm = TRUE)

# A tibble: 4 x 5
#  id    ALL    `2017` `2018` `2019`
#  <chr> <chr>  <chr>  <chr>  <chr> 
#1 aa    tv     tv     NA     NA    
#2 ss    web    NA     web    NA    
#3 dd    book   NA     NA     book  
#4 qq    web tv web    NA     tv    

Это сработало для меня после установки разрабатываемой версии tidyr, выполнив

devtools::install_github("tidyverse/tidyr")
1 голос
/ 20 марта 2019

Для полноты (и для дополнения LocoGris 'data.table answer ) существуют три других подхода, которые обновляют input по ссылке , т. Е. Без копированиявесь объект данных.

Все подходы возвращают один и тот же результат и могут обрабатывать произвольное количество лет.

Обратите внимание, что id должен быть уникальным ключом, то есть без каких-либо дубликатов.

Изменение формы, na.omit(), совокупность

library(data.table)
setDT(input)[, ALL := melt(input, id.var = "id")[, toString(na.omit(value)), by = id]$V1][]
   id 2017 2018 2019     ALL
1: aa   tv <NA> <NA>      tv
2: ss <NA>  web <NA>     web
3: dd <NA> <NA> book    book
4: qq  web <NA>   tv web, tv

Кстати, изменение формы с широкого на длинный формат обеспечивает более краткий способ хранения малонаселенных данных.

melt(input, id.var = "id", na.rm = TRUE)
   id variable value
1: aa     2017    tv
2: qq     2017   web
3: ss     2018   web
4: dd     2019  book
5: qq     2019    tv

Изменить, агрегировать, объединить

library(data.table)
setDT(input)[melt(input, id.var = "id", na.rm = TRUE)[, toString(value), by = id],
             on = "id", ALL := V1][]

При этом значения NA удаляются из результата шага изменения формы, который искажаеторигинальный порядок строк из-за множества NA.Следовательно, требуется обновление соединения .

Filter(), совокупность

library(data.table)
setDT(input)[, ALL := .SD[, toString(Filter(Negate(is.na), .SD)), by = id]$V1][]
0 голосов
/ 18 марта 2019

A data.table подход:

library(data.table)
library(tidyverse)
input <- data.table(
  id = c('aa', 'ss', 'dd', 'qq'),
  '2017' = c('tv', NA, NA, 'web'),
  '2018' = c(NA, 'web', NA, NA),
  '2019' = c(NA, NA, 'book', 'tv')
)

""-> input[is.na(input)]
input[, ALL:=paste0(.SD,collapse=" "), .SDcols =2:length(input), by=seq_len(nrow(input))] 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...