Разделить символ в столбце и имени

#r #split #dataframe

#r #сплит #фрейм данных

Вопрос:

Я хочу разделить персонажей. Хотя у меня есть большой фрейм данных для работы, следующий небольшой пример покажет, что нужно сделать.

   mydf <- data.frame (name = c("L1", "L2", "L3"), 
    M1 = c("AC", "AT", NA), M2 = c("CC", "--", "TC"), M3 = c("AT", "TT", "AG"))
 

Я хочу разделить символы для переменных M1 на M3 (в реальном наборе данных у меня > 6000 переменных)

   name  M1a M1b   M2a M2b  M3a  M3b 
   L1   A    C    C    C    A     T
   L2   A    T    -    -    T     T
   L3   NA   NA   T     C    A     G
 

Я попробовал следующие коды:

 func<- function(x) {sapply( strsplit(x, ""),
                     match, table= c("A","C","T","G", "--", NA))}

odataframe <- data.frame(apply(mydf, 1, func) )
colnames(odataframe) <-  paste(rep(names(mydf), each = 2), c("a", "b"), sep = "")
odataframe
 

Ответ №1:

Вот так:

 splitCol <- function(x){
  x <- as.character(x)
  x[is.na(x)] <- "$"
  z <- matrix(unlist(strsplit(x, split="")), ncol=2, byrow=TRUE)
  z[z=="$"] <- NA
  z
}


newdf <- as.data.frame(do.call(cbind, lapply(mydf[, -1], splitCol)))
names(newdf) <- paste(rep(names(mydf[, -1]), each=2), c("a", "b"), sep="")
newdf <- data.frame(mydf[, 1, drop=FALSE], newdf)

newdf
  name  M1a  M1b M2a M2b M3a M3b
1   L1    A    C   C   C   A   T
2   L2    A    T   -   -   T   T
3   L3 <NA>  <NA   T   C   A   G
 

Комментарии:

1. спасибо за быстрый ответ, приятно, но все же кажется, что есть проблема, связанная с обработкой NA в M1a и M1b, в третьей строке должны быть NA и NA (не NA и A)

2. Я исправил это за несколько секунд до вашего комментария. Попробуйте еще раз.

3. Это может быть очень применимо ко мне. Спасибо за публикацию. Я объединил его в функцию и решил поделиться. Спасибо за сообщение.

Ответ №2:

Код Андри как воспроизводимая функция

 splitCol <- function(dataframe, splitVars=names(dataframe)){
split.DF <- dataframe[,splitVars]
keep.DF <- dataframe[, !names(dataframe) %in% c(splitVars)]

X <- function(x)matrix(unlist(strsplit(as.character(x), split="")), ncol=2, byrow=TRUE)

newdf <- as.data.frame(do.call(cbind, suppressWarnings(lapply(split.DF, X))) )
names(newdf) <- paste(rep(names(split.DF), each=2), c(".a", ".b"), sep="") 
data.frame(keep.DF,newdf)
}
 

Проверьте это

 splitCol(mydf)
splitCol(mydf, c('M1','M2'))
 

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