Coluna de divisão no delimitador no quadro de dados

Eu gostaria de dividir uma coluna em dois dentro do quadro de dados com base em um delimitador. Por exemplo,

a|b b|c 

tornar-se

 ab bc 

dentro de um quadro de dados.

Obrigado!

   

@Taesung Shin está certo, mas apenas um pouco mais de magia para transformá-lo em data.frame . Eu adicionei uma linha “x | y” para evitar ambigüidades:

 df < - data.frame(ID=11:13, FOO=c('a|b','b|c','x|y')) foo <- data.frame(do.call('rbind', strsplit(as.character(df$FOO),'|',fixed=TRUE))) 

Ou, se você quiser replace as colunas no data.frame existente:

 within(df, FOO< -data.frame(do.call('rbind', strsplit(as.character(FOO), '|', fixed=TRUE)))) 

Que produz:

  ID FOO.X1 FOO.X2 1 11 ab 2 12 bc 3 13 xy 

Hadley tem uma solução muito elegante para fazer isso dentro de frames de dados em seu pacote colsplit , usando a function colsplit .

 require(reshape) > df < - data.frame(ID=11:13, FOO=c('a|b','b|c','x|y')) > df ID FOO 1 11 a|b 2 12 b|c 3 13 x|y > df = transform(df, FOO = colsplit(FOO, split = "\\|", names = c('a', 'b'))) > df ID FOO.a FOO.b 1 11 ab 2 12 bc 3 13 xy 

O recém-popular pacote tidyr faz isso com separate . Ele usa expressões regulares, então você terá que escaping do |

 df < - data.frame(ID=11:13, FOO=c('a|b', 'b|c', 'x|y')) separate(data = df, col = FOO, into = c("left", "right"), sep = "\\|") ID left right 1 11 ab 2 12 bc 3 13 xy 

embora nesse caso os padrões sejam espertos o suficiente para funcionar (ele procura por caracteres não-alfanuméricos para dividir).

 separate(data = df, col = FOO, into = c("left", "right")) 

Acabou de se deparar com esta questão, uma vez que foi ligada em uma pergunta recente sobre SO .

Plugue sem vergonha de uma resposta: Use o cSplit do meu pacote “splitstackshape”:

 df < - data.frame(ID=11:13, FOO=c('a|b','b|c','x|y')) library(splitstackshape) cSplit(df, "FOO", "|") # ID FOO_1 FOO_2 # 1 11 ab # 2 12 bc # 3 13 xy 

Essa function específica também manipula a divisão de várias colunas, mesmo que cada coluna tenha um delimitador diferente:

 df < - data.frame(ID=11:13, FOO=c('a|b','b|c','x|y'), BAR = c("A*B", "B*C", "C*D")) cSplit(df, c("FOO", "BAR"), c("|", "*")) # ID FOO_1 FOO_2 BAR_1 BAR_2 # 1 11 ab AB # 2 12 bc BC # 3 13 xy CD 

Essencialmente, é um invólucro de conveniência sofisticado para o uso de read.table(text = some_character_vector, sep = some_sep) e vincula essa saída ao data.frame original. Em outras palavras, outra abordagem A base R poderia ser:

 df < - data.frame(ID=11:13, FOO=c('a|b','b|c','x|y')) cbind(df, read.table(text = as.character(df$FOO), sep = "|")) ID FOO V1 V2 1 11 a|bab 2 12 b|cbc 3 13 x|yxy 
 strsplit(c('a|b','b|c'),'|',fixed=TRUE) 

Combinar as respostas de @Ramnath e @ Tommy permitiu-me encontrar uma abordagem que funciona na base R para uma ou mais colunas.

Uso básico:

 > df = data.frame( + id=1:3, foo=c('a|b','b|c','c|d'), + bar=c('p|q', 'r|s', 's|t'), stringsAsFactors=F) > transform(df, test=do.call(rbind, strsplit(foo, '|', fixed=TRUE)), stringsAsFactors=F) id foo bar test.1 test.2 1 1 a|bp|qab 2 2 b|cr|sbc 3 3 c|ds|tcd 

Múltiplas colunas:

 > transform(df, lapply(list(foo,bar), + function(x)do.call(rbind, strsplit(x, '|', fixed=TRUE))), stringsAsFactors=F) id foo bar X1 X2 X1.1 X2.1 1 1 a|bp|qabpq 2 2 b|cr|sbcrs 3 3 c|ds|tcdst 

Melhor nomeação de várias colunas divididas:

 > transform(df, lapply({l< -list(foo,bar);names(l)=c('foo','bar');l}, + function(x)do.call(rbind, strsplit(x, '|', fixed=TRUE))), stringsAsFactors=F) id foo bar foo.1 foo.2 bar.1 bar.2 1 1 a|bp|qabpq 2 2 b|cr|sbcrs 3 3 c|ds|tcdst