Columna de división - pero sólo si contians uno ore más caracteres especiales
Encontré algunas preguntas en esta dirección, pero no pude aplicar las soluciones a mi problema específico: Tengo una columna bastante desordenada de un marco de datos con direcciones. Esto significa que puede haber células vacías, números, números y texto combinados - y puede haber uno o más caracteres especiales entre ellos.
En un primer paso, quiero dividir todos los valores en el primer personaje especial. He probado varias opciones que funcionan parcialmente. Sin embargo, el problema parece ser que algunas células no contienen caracteres especiales, causando un error en la función.
Por ejemplo, el siguiente código pone sólo el carácter especial en la nueva columna b
, pero realmente no divide las columnas:
df <- df %>%
separate(address, into = c("a", "b"), sep = "[^[:punct:]]+", remove = FALSE)
Así que lo ideal que quiero lograr es lo siguiente: Si hay un personaje especial en la celda, dividirlo en el primer personaje especial, todo lo que queda del primer personaje especial en column a
, todo bien en column b
. Si no hay carácter especial, ponga todo en column a
y NA
dentro column b
.
¿Tengo que envolver mi código en un ifelse
- declaración? ¿O hay alguna otra sugerencia?
¡Gracias!
Editar: según lo solicitado, algunos datos de muestra:
library(dplyr)
test <- as.data.frame(c("2", "97/7", "17/7-8", "7E", "800E/7", "17", "", "0", "2/15", "17+18", "17/7/8", "19", "2/2/4", "9-7/8")) %>%
rename(address = 1)
Pregunta hecha hace 3 años, 5 meses, 0 días - Por scriptwarrior
5 Respuestas:
-
Puedes usar
separate
utilizandoextra = 'merge'
yfill = 'right'
tidyr::separate(test, address, into = c("a", "b"), '[[:punct:]]', extra = 'merge', fill = 'right', remove = FALSE) # address a b #1 2 2
#2 97/7 97 7 #3 17/7-8 17 7-8 #4 7E 7E #5 800E/7 800E 7 #6 17 17 #7 #8 0 0 #9 2/15 2 15 #10 17+18 17 18 #11 17/7/8 17 7/8 #12 19 19 #13 2/2/4 2 2/4 #14 9-7/8 9 7/8 Respondida el Dec 17, 2020 a las 09:45 - por htmlhelix
Votos positivos: 0 | Votos negativos: 0 -
Uso
strsplit
con su expresión regular funciona. Podemos ponerlo en unlapply
a bucle sobre las columnas. Uso`length<-()`
ajustamos las longitudes de los elementos de la lista a su máximo para poder crear undata.frame
.r <- el(lapply(test, strsplit, "[[:punct:]]", perl=TRUE)) as.data.frame(t(sapply(r, `length<-`, max(lengths(r))))) # V1 V2 V3 # 1 2
# 2 97 7 # 3 17 7 8 # 4 7E # 5 800E 7 # 6 17 # 7 # 8 0 # 9 2 15 # 10 17 18 # 11 17 7 8 # 12 19 # 13 2 2 4 # 14 9 7 8 Del mismo modo podemos hacerlo en la primera ocurrencia: Podemos usar
sub
para reemplazar la primera ocurrencia con algo, digamos"£"
y luego dividirlo ahí.test[] <- lapply(test, sub, pat="[[:punct:]]", rep="£") r <- el(lapply(test, strsplit, "£")) as.data.frame(t(sapply(r, `length<-`, max(lengths(r))))) # V1 V2 # 1 2
# 2 97 7 # 3 17 7-8 # 4 7E # 5 800E 7 # 6 17 # 7 # 8 0 # 9 2 15 # 10 17 18 # 11 17 7/8 # 12 19 # 13 2 2/4 # 14 9 7/8 Respondida el Dec 17, 2020 a las 09:55 - por logicloom
Votos positivos: 0 | Votos negativos: 0 -
Esto funciona:
library(dplyr) library(tidyr) df %>% separate(c1, c('a','b'), sep = '[^A-z0-9_]') a b 1 ab cd 2 pq rj 3 xy z 4 abcd
Datos utilizados:
df c1 1 ab$cd 2 pq%rj 3 xy#z 4 abcd
Respondida el Dec 17, 2020 a las 10:04 - por techtrailblazer
Votos positivos: 0 | Votos negativos: 0 -
Para lograr la división de la columna de direcciones de acuerdo a la presencia de caracteres especiales, puedes utilizar la función
mutate()
junto conifelse()
para realizar la condición que mencionas.Aquí te dejo un ejemplo de cómo podrías hacerlo:
```R library(dplyr)
Crear los datos de ejemplo
test <- as.data.frame(c("2", "97/7", "17/7-8", "7E", "800E/7", "17", "", "0", "2/15", "17+18", "17/7/8", "19", "2/2/4", "9-7/8")) %>% rename(address = 1)Dividir los valores en dos columnas según la presencia de caracteres especiales
test <- test %>% mutate(a = ifelse(grepl("[[:punct:]]", address), sub("([[:punct:]]).$", "\1", address), address), b = ifelse(grepl("[[:punct:]]", address), sub(".([[:punct:]]).*", "\1", address), NAcharacter))#
Respondida el Dec 18, 2020 a las 09:44 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
Claro, echemos un vistazo a tu problema con la separación de columnas en un DataFrame. Entiendo que deseas dividir los datos en la primera aparición de un carácter especial, pero solo cuando exista ese carácter en la celda. Aquí tienes una solución que puedes usar:
library(dplyr) library(stringr) test <- as.data.frame(c("2", "97/7", "17/7-8", "7E", "800E/7", "17", "", "0", "2/15", "17+18", "17/7/8", "19", "2/2/4", "9-7/8")) |> mutate(address = 1)
Divide la cadena en el primer carácter especial (si existe)
test <- test |> mutate( a = case_when( str_contains(address, "[^[:punct:]]+") ~ str_sub(address, 1, str_locate(address, "[^[:punct:]]+") - 1), TRUE ~ address ), b = case_when( str_contains(address, "[^[:punct:]]+") ~ str_sub(address, str_locate(address, "[^[:punct:]]+") + 1), TRUE ~ NA ) ) print(test)Explicación:
- Caso cuando la celda no tiene un carácter especial:
- `TRUE ~ address` devuelve el valor de la celda `address` si no hay un carácter especial.
- Caso cuando la celda tiene un carácter especial:
- `str_sub(address, 1, str_locate(address, "[^[:punct:]]+") - 1)` extrae la subsecuencia desde el primer carácter hasta el carácter anterior al primer carácter especial.
- `str_sub(address, str_locate(address, "[^[:punct:]]+") + 1)` extrae la subsecuencia desde el carácter posterior al primer carácter especial hasta el final de la cadena.
Espero que esto resuelva tu problema. Avísame si tienes alguna otra inquietud.
Respondida el Dec 18, 2020 a las 09:54 - por Gemini
Votos positivos: 0 | Votos negativos: 0