Объединение нескольких столбцов с помощью Tidyr's Unite путем ссылки на похожие имена столбцов

library(tidyr)
library(dplyr)
library(tidyverse)

Ниже приведен код простого фрейма данных. У меня есть некоторые беспорядочные данные, которые были экспортированы с разбросанными по разным столбцам категориями факторов столбца.

Client<-c("Client1","Client2","Client3","Client4","Client5")
Sex_M<-c("Male","NA","Male","NA","Male")
Sex_F<-c(" ","Female"," ","Female"," ")
Satisfaction_Satisfied<-c("Satisfied"," "," ","Satisfied","Satisfied")
Satisfaction_VerySatisfied<-c(" ","VerySatisfied","VerySatisfied"," "," ")
CommunicationType_Email<-c("Email"," "," ","Email","Email")
CommunicationType_Phone<-c(" ","Phone ","Phone "," "," ")
DF<-tibble(Client,Sex_M,Sex_F,Satisfaction_Satisfied,Satisfaction_VerySatisfied,CommunicationType_Email,CommunicationType_Phone)

Я хочу перекомбинировать категории в отдельные столбцы, используя "объединить" tidyr.

DF<-DF%>%unite(Sat,Satisfaction_Satisfied,Satisfaction_VerySatisfied,sep=" ")%>%
unite(Sex,Sex_M,Sex_F,sep=" ")

Тем не менее, мне нужно написать несколько «объединяющих» строк, и я чувствую, что это нарушает правило трех раз, поэтому должен быть способ упростить это, тем более что мои реальные данные содержат десятки столбцов, которые необходимо объединить. Есть ли способ использовать «объединить» один раз, но каким-то образом ссылаться на совпадающие имена столбцов, чтобы все имена столбцов были похожи (например, содержащие «Пол» для «Sex_M» и «Sex_F» и «CommunicationType» для «CommunicationType_Email» и "CommunicationType_Phone") сочетаются с приведенной выше формулой?

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


person Mike    schedule 08.03.2017    source источник


Ответы (2)


Мы можем использовать unite

library(tidyverse)
DF %>% 
    unite(Sat, matches("^Sat"))

Для нескольких случаев, возможно

gather(DF, Var, Val, -Client, na.rm = TRUE) %>%
        separate(Var, into = c("Var1", "Var2")) %>%
        group_by(Client, Var1) %>% 
        summarise(Val = paste(Val[!(is.na(Val)|Val=="")], collapse="_")) %>%
        spread(Var1, Val)
#  Client CommunicationType  Satisfaction    Sex
#*   <chr>             <chr>         <chr>  <chr>
#1 Client1             Email     Satisfied   Male
#2 Client2             Phone VerySatisfied Female
#3 Client3             Phone VerySatisfied   Male
#4 Client4             Email     Satisfied Female
#5 Client5             Email     Satisfied   Male
person akrun    schedule 08.03.2017

Что-то вроде этого? Если у вас много столбцов.

result<-with(new.env(),{
  Client<-c("Client1","Client2","Client3","Client4","Client5")
  Sex_M<-c("Male","NA","Male","NA","Male")
  Sex_F<-c(" ","Female"," ","Female"," ")
  Satisfaction_Satisfied<-c("Satisfied"," "," ","Satisfied","Satisfied")
  Satisfaction_VerySatisfied<-c(" ","VerySatisfied","VerySatisfied"," "," ")
  CommunicationType_Email<-c("Email"," "," ","Email","Email")
  CommunicationType_Phone<-c(" ","Phone ","Phone "," "," ")
  x<-ls()
  categories<-unique(sub("(.*)_(.*)", "\\1", x))
  df<-setNames(data.frame( lapply(x, function(y) get(y))), x)
  for(nm in categories){
    df<-unite_(df, nm, x[contains(vars = x, match = nm)])
  }
  return(df)
})

Client CommunicationType    Satisfaction       Sex
1 Client1           Email_      Satisfied_      _Male
2 Client2           _Phone   _VerySatisfied Female_NA
3 Client3           _Phone   _VerySatisfied     _Male
4 Client4           Email_      Satisfied_  Female_NA
5 Client5           Email_      Satisfied_      _Male
person Jean    schedule 08.03.2017