¿Cómo dividir una cadena en múltiples columnas?
Tengo una cuerda que se ve así:
# character string
string <- "lambs: cows: 281 chickens: 20 goats: 3 trees: 13"
Quiero crear un marco de datos que se parezca a esto:
# structure
lambs <- NA
cows <- 281
chickens <- 20
goats <- 3
trees <- 13
# dataframe
df <-
cbind(lambs, cows, chickens, goats, trees) %>%
as.data.frame()
Esto es lo que he intentado hasta ahora:
# split string
test <- strsplit(string, " ")
test
Los datos son bastante inmundos por lo que el espaciado no siempre es consistente, y a veces hay corderos y a veces no hay corderos (como en: "lamb: 5 cow: 50"
y "lamb: cow: 40"
. ¿Cuál es la manera más fácil de hacer esto usando tidyverse?
Pregunta hecha hace 3 años, 4 meses, 29 días - Por devninjax
5 Respuestas:
-
Puedes usar
str_match_all
y pasar el patrón para extraer.tmp <- stringr::str_match_all(string, '\\s*(.*?):\\s*(\\d+)?')[[1]][, -1] data <- type.convert(data.frame(tmp), as.is = TRUE) # X1 X2 #1 lambs NA #2 cows 281 #3 chickens 20 #4 goats 3 #5 trees 13
Esto divide los datos en dos columnas donde la primera columna es todo antes del colon (
:
) excepto el espacio blanco y la segunda columna es el número seguido después de él. He hecho la parte número como opcional para dar cabida a casos como'lambs'
que no tienen número.Respondida el Dec 18, 2020 a las 04:00 - por codealchemyf00f
Votos positivos: 0 | Votos negativos: 0 -
Prueba esto:
gre <- gregexpr("\\b([A-Za-z]+:\\s*[0-9]*)\\b", string) regmatches(string, gre) # [[1]] # [1] "lambs: " "cows: 281" "chickens: 20" "goats: 3" "trees: 13" lapply(regmatches(string, gre), strcapture, pattern = "(.*):(.*)", proto = list(anim = character(0), n = character(0))) # [[1]] # anim n # 1 lambs # 2 cows 281 # 3 chickens 20 # 4 goats 3 # 5 trees 13 frames <- lapply(regmatches(string, gre), strcapture, pattern = "(.*):(.*)", proto = list(anim = character(0), n = character(0)))
Si usted tiene múltiples cadenas (y no sólo una), entonces esto asegura que cada cadena se procesa y luego todos los datos se combinan.
alldat <- do.call(rbind, frames) alldat$n <- as.integer(alldat$n) alldat # anim n # 1 lambs NA # 2 cows 281 # 3 chickens 20 # 4 goats 3 # 5 trees 13
Si en su lugar realmente necesita los datos en un formato "total", entonces
do.call(rbind, lapply(frames, function(z) do.call(data.frame, setNames(as.list(as.integer(z$n)), z$anim)))) # lambs cows chickens goats trees # 1 NA 281 20 3 13
Respondida el Dec 18, 2020 a las 04:08 - por coderchampion
Votos positivos: 0 | Votos negativos: 0 -
Puedes intentarlo.
read.table
. El tema "no hay corderos" se puede resolver poniendo en cero congsub
.r <- na.omit(unlist(read.table(text=gsub(": ", " 0", string), sep=" "))) r <- replace(r, r == 0, NA) ## long format type.convert(as.data.frame(matrix(r, ncol=2, byrow=TRUE)), as.is=TRUE) # V1 V2 # 1 lambs NA # 2 cows 281 # 3 chickens 20 # 4 goats 3 # 5 trees 13 ## wide format setNames(type.convert(r[seq(r) %% 2 == 0]), r[seq(r) %% 2 == 1]) # lambs cows chickens goats trees # NA 281 20 3 13
Respondida el Dec 18, 2020 a las 04:15 - por pixelpioneerbbb5
Votos positivos: 0 | Votos negativos: 0 -
Parece que estás tratando de dividir una cadena en múltiples columnas para crear un marco de datos en R. Una forma de lograr esto es limpiar la cadena y luego dividirla en columnas utilizando el paquete tidyverse. Aquí tienes un ejemplo de cómo podrías hacerlo:
```R library(tidyverse)
Caracter string
string <- "lambs: cows: 281 chickens: 20 goats: 3 trees: 13"Limpiar la cadena
string_clean <- gsub(":", "", string)Eliminar los ":" de la cadena
string_clean <- gsub("\\s+", ":", string_clean)Reemplazar múltiples espacios en blanco con ":"
string_clean <- gsub(": ", ":", string_clean)Eliminar un espacio después de los ":" para tener un formato consistente
string_clean <- gsub(":$", "", string_clean)Eliminar ":" al final de la cadena
Dividir la cadena en columnas
df <- tibble::tibble(strsplit(stringclean, ":", simplify = TRUE)) %>% dplyr::mutate(value = as.numeric(str_trimRespondida el Dec 19, 2020 a las 04:01 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
Puedes usar la función
separate()
del paquetetidyr
para dividir la cadena en múltiples columnas. Esta función te permite especificar un patrón para dividir la cadena y asignar los resultados a nuevas columnas en un marco de datos. Aquí tienes un ejemplo de cómo puedes usarseparate()
para resolver tu problema:library(tidyverse) string <- "lambs: cows: 281 chickens: 20 goats: 3 trees: 13"
Divide la cadena en columnas usando " " como separador
test <- strsplit(string, " ")Convierte la lista resultante en un marco de datos
test_df <- data.frame(test)Divide las columnas usando ":" como separador y asigna los resultados a nuevas columnas
result_df <- test_df %>% separate(X1, into = c("animal", "count"), sep = ":")Convierte los valores de "count" a numéricos
result_df$count <- as.numeric(result_df$count)El marco de datos resultante tendrá la siguiente estructura:
A tibble: 5 x 2
animal count1 lambs NA 2 cows 281 3 chickens 20 4 goats 3 5 trees 13 Como puedes ver, se ha creado una columna
animal
que contiene los nombres de los animales y una columnacount
que contiene los recuentos correspondientes. El valorNA
en la filalambs
se debe a que no había un valor de recuento para los corderos en la cadena original.Respondida el Dec 19, 2020 a las 04:04 - por Gemini
Votos positivos: 0 | Votos negativos: 0