Объединение содержимого нескольких столбцов в один - PullRequest
0 голосов
/ 14 января 2020

У меня есть фрейм данных с пятью столбцами и 6 строками (на самом деле их гораздо больше, я просто пытаюсь упростить вопросы):

One Two Three   Four    Five
Cat NA  NA  NA  NA
NA  Dog NA  NA  NA
NA  NA  NA  Mouse   NA
Cat NA  Rat NA  NA
Horse   NA  NA  NA  NA
NA NA NA NA NA

Теперь я хотел бы объединить всю информацию в новом сингле столбец («Сводка»), например так:

Summary
Cat
Dog
Mouse
Error
Horse
NA

Обратите внимание на сообщение об ошибке в четвертой строке «Сводка», поскольку при объединении было зарегистрировано два разных значения. Я попытался взглянуть на функцию 'coalesce' в пакете dplyr, но, похоже, она действительно не выполняет то, что мне нужно. Заранее спасибо.

Отредактировано : я добавил шестую строку, чтобы указать, что в случае всех «NA» в строке, я хотел бы получить «NA», а не «Errors» в мой столбец "Резюме". Извините, если это не было ясно в моем первом посте.

Ответы [ 5 ]

2 голосов
/ 14 января 2020

Вот идея через apply,

apply(df, 1, function(i){i1 <- i[!is.na(i)]; if(length(i1) > 1){'Error'}else{i1}})
#[1] "Cat"   "Dog"   "Mouse" "Error" "Horse"
1 голос
/ 14 января 2020

Я бы использовал apply для решения этой проблемы, так как вам нужно обрабатывать определенные c случаи. EG

df <- structure(list(One = structure(c(1L, NA, NA, 1L, 2L), .Label = c("Cat", 
"Horse", "NA"), class = "factor"), Two = structure(c(NA, 1L, 
NA, NA, NA), .Label = c("Dog", "NA"), class = "factor"), Three = structure(c(NA, 
NA, NA, 2L, NA), .Label = c("NA", "Rat"), class = "factor"), 
    Four = structure(c(NA, NA, 1L, NA, NA), .Label = c("Mouse", 
    "NA"), class = "factor"), Five = structure(c(NA_integer_, 
    NA_integer_, NA_integer_, NA_integer_, NA_integer_), .Label = "NA", class = "factor")), row.names = c(NA, 
-5L), class = "data.frame")


apply(df, 1, function(row) if(sum(!is.na(row)) == 1) na.omit(row)[[1]] else "Error")
#> [1] "Cat"   "Dog"   "Mouse" "Error" "Horse"

Создано в 2020-01-14 пакетом представ (v0.3.0)

0 голосов
/ 14 января 2020

Вы также можете использовать coalesce

df %>%
  mutate_all(as.character) %>% 
  mutate(coal = coalesce(!!!syms(names(.))),
         sum_na = rowSums(!is.na(.)),
         result = if_else(sum_na == 1,coal,"Error")) %>% 
  select(result)
0 голосов
/ 14 января 2020
  • Вот еще одно базовое решение R, использующее sapply() + ifelse()
r <- sapply(as.list(as.data.frame(t(df))),
            function(x) ifelse(length(levels(x))==1, na.omit(as.vector(x)),"Error"))

, такое что

> r
     V1      V2      V3      V4      V5 
  "Cat"   "Dog" "Mouse" "Error" "Horse"
  • Или вы можете используйте sapply() + ifelse()
r <- apply(df, 1, function(x) ifelse(length(z <- unique(na.omit(x)))==1, z,"Error"))

так, чтобы

> r
[1] "Cat"   "Dog"   "Mouse" "Error" "Horse"

DATA

df <- structure(list(One = c("Cat", NA, NA, "Cat", "Horse"), Two = c(NA, 
"Dog", NA, NA, NA), Three = c(NA, NA, NA, "Rat", NA), Four = c(NA, 
NA, "Mouse", NA, NA), Five = c(NA, NA, NA, NA, NA)), class = "data.frame", row.names = c(NA, 
-5L))
0 голосов
/ 14 января 2020

Другой способ - использовать новую функцию pivot_ в dplyr:

df <- tribble(~One, ~Two, ~Three,   ~Four,    ~Five,
              "Cat", NA,  NA,  NA,  NA,
              NA,  "Dog", NA,  NA,  NA,
              NA,  NA,  NA,  "Mouse",   NA,
              "Cat", NA,  "Rat", NA,  NA,
              "Horse",   NA,  NA,  NA,  NA)

df %>% 
  pivot_longer(names_to = "variable", values_to = "Summary", 
               values_drop_na = TRUE, cols = One:Five) %>% 
  distinct(Summary)
# # A tibble: 5 x 1
# Summary
# <chr>  
# 1 Cat    
# 2 Dog    
# 3 Mouse  
# 4 Rat    
# 5 Horse  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...