Separe linhas em colunas usando o primeiro caractere dividido

8

Ter um dataframe como este:

data.frame(text = c("separate1: and: more","another 20: 42")

Como é possível separar usando o primeiro: em cada linha? Exemplo de saída esperada

data.frame(text1 = c("separate1","another 20"), text2 = c("and: more","42")
Nathalie
fonte
1
Isso responde sua pergunta? Dividir a coluna da sequência de quadros de dados em várias colunas
Claudiu Papasteri
2
@ClaudiuPapasteri nope. Isso não é exatamente o mesmo e o fato de a solução aceita funcionar aqui é acidental. Enganar o que você sugere pode ser muito enganador
Sotos 10/02
@ Sotos sim, você está certo. Eu não estava prestando atenção, duas das soluções funcionam, mas por coincidência. Desculpe por isso. Adicionei meus dois centavos ao pool de soluções como desculpa por sinalizar errado.
Claudiu Papasteri

Respostas:

4
library(reshape2)

df <- data.frame(text = c("separate1: and: more","another 20: 42")

colsplit(df$text, ":", c("text1", "text2"))
Georgery
fonte
5

Na base, você pode usar regexprpara encontrar a posição do primeiro, :que pode ser usada para extrair substrings e trimwsremover espaços em branco.

x <- c("separate1: and: more","another 20: 42")

i <- regexpr(":", x)
data.frame(text1 = trimws(substr(x, 1, i-1)), text2 = trimws(substring(x, i+1)))
#       text1     text2
#1  separate1 and: more
#2 another 20        42
GKi
fonte
4

Você pode usar str_split_fixedfrom stringrpackage, que por padrão será dividido no primeiro delimitador, ou seja,

stringr::str_split_fixed(d1$text, ':', 2)

#     [,1]         [,2]        
#[1,] "separate1"  " and: more"
#[2,] "another 20" " 42"       
Sotos
fonte
4
df <- data.frame(text = c("separate1: and: more","another 20: 42"))

df$text1 <- gsub(':.*', '', df$text)
df$text2 <- gsub('^[^:]+: ', '', df$text)

df
#                   text      text1     text2
# 1 separate1: and: more  separate1 and: more
# 2       another 20: 42 another 20        42
IceCreamToucan
fonte
4

Usando tidyr :

library(dplyr)
library(tidyr)

df %>% 
  separate(text, c("a", "b"), sep = ": ", extra = "merge")
#            a         b
# 1  separate1 and: more
# 2 another 20        42
zx8754
fonte
3

Outra solução R básica

df <- do.call(rbind,lapply(as.character(df$text), function(x) {
  k <- head(unlist(gregexpr(":",x)),1)
  data.frame(text1 = substr(x,1,k-1),
             text2 = substr(x,k+1,nchar(x)))
}))

de tal modo que

> df
       text1      text2
1  separate1  and: more
2 another 20         42
ThomasIsCoding
fonte
2

Desculpe, @Sotos está certo, isso não é uma cópia. Aqui está outra solução base que se divide na primeira ocorrência do delimitador.

df <- data.frame(text = c("separate1: and: more","another 20: 42"))

list <- apply(df, 1, function(x) regmatches(x, regexpr(":", x), invert = TRUE))
df <- data.frame(matrix(unlist(list), nrow = length(list), byrow = TRUE))

df
#>           X1         X2
#> 1  separate1  and: more
#> 2 another 20         42

Criado em 2020-02-10 pelo pacote reprex (v0.2.1)

Claudiu Papasteri
fonte
2

O pobre velho ?utils::strcapturenunca recebe respeito:

strcapture("^(.+?):(.+$)", df$text, proto=list(text1="", text2=""))
#       text1      text2
#1  separate1  and: more
#2 another 20         42

Inserido de volta:

cbind(df, strcapture("^(.+?):(.+$)", df$text, proto=list(text1="", text2="")))
#                  text      text1      text2
#1 separate1: and: more  separate1  and: more
#2       another 20: 42 another 20         42
thelatemail
fonte