Separe las filas en columnas con el primer carácter dividido

8

Tener un marco de datos como este:

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

¿Cómo es posible separar usando el primero: en cada fila? Ejemplo de salida esperada

data.frame(text1 = c("separate1","another 20"), text2 = c("and: more","42")
Nathalie
fuente
1
¿Responde esto a tu pregunta? Dividir la columna de la cadena del marco de datos en varias columnas
Claudiu Papasteri
2
@ClaudiuPapasteri no. Eso no es exactamente lo mismo y el hecho de que la solución aceptada funcione aquí es accidental. Duplicar con lo que sugieres puede ser muy engañoso
Sotos
@Sotos sí, tienes razón. No estaba prestando atención, dos de las soluciones funcionan pero casualmente. Lo siento por eso. Agregué mis dos centavos al grupo de soluciones como disculpa por un indicador incorrecto.
Claudiu Papasteri

Respuestas:

4
library(reshape2)

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

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

En la base , puede usar regexprpara encontrar la posición del primero :que puede usarse para extraer subcadenas y trimwseliminar espacios en blanco.

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
fuente
4

Se puede utilizar str_split_fixedde stringrpaquete que va por división de valor en el primer delimitador, es decir,

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

#     [,1]         [,2]        
#[1,] "separate1"  " and: more"
#[2,] "another 20" " 42"       
Sotos
fuente
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
fuente
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
fuente
3

Otra solución base R

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

tal que

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

Lo sentimos, @Sotos tiene razón, esto no es un duplicado. Aquí hay otra solución base que se divide en la primera aparición del 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

Creado el 10/02/2020 por el paquete reprex (v0.2.1)

Claudiu Papasteri
fuente
2

Pobre de edad ?utils::strcapturenunca recibe ningún respeto:

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

Insertado de nuevo:

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
fuente