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")


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"))

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

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"       

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

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

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

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)


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.