Israel, parte de nuestro equipo, nos ha hecho el favor de redactar este artículo ya que conoce muy bien el tema.
Solución:
Con un data.table
solución, puedes usar tstrsplit
:
library(data.table)
df <- data.table::data.table(
color = c("red;blue", "red;green")
)
df[, c("col1","col2") := tstrsplit(color, ";", fixed = TRUE)]
df[, "green" := (col2 == "green")]
df
# color col1 col2 green
# 1: red;blue red blue FALSE
# 2: red;green red green TRUE
Si no está familiarizado con data.table
operador de actualización por referencia :=
, data.table
las viñetas son un buen punto de partida. La opción fixed = TRUE
en tstrsplit
asume que siempre tiene el mismo número de elementos en su lista separada por comas.
Hay una solución que, creo, se adapta más a una situación en la que tienes más de unos pocos valores. Usando repetidamente lapply
, puede agregar una serie de columnas a su data.table
Empezando de nuevo con df
:
df <- data.table::data.table(
color = c("red;blue", "red;green")
)
Vocación lapply
con grepl
para buscar el color relevante, actualizamos por referencia nuestro objeto (tenga en cuenta que puede usar más de tres colores):
lapply(c("red","green","blue"), function(x)
df[grepl(x, color), c(as.character(x)) := TRUE]
)
#[[1]]
#[[2]]
# color red green blue
#1: red;blue TRUE NA TRUE
#2: red;green TRUE TRUE NA
#[[3]]
# color red green blue
#1: red;blue TRUE NA TRUE
#2: red;green TRUE TRUE NA
No es necesario reasignar el marco de datos. Ha sido actualizado por referencia. Solo la última ranura de df
nos interesa. Finalmente, seleccionando este y configurando NAs
a FALSE
:
df <- df[[length(df)]]
df[is.na(df)] <- FALSE
df
# color red green blue
# 1: red;blue TRUE FALSE TRUE
# 2: red;green TRUE TRUE FALSE
Espero eso ayude
Nosotros podemos usar str_detect
library(dplyr)
library(stringr)
df %>%
mutate(green = +(str_detect(colors, 'green')))
Actualizar
Si quisiéramos nuevas columnas
library(qdapTools)
cbind(df, mtabulate(strsplit(df$colors, ";")))
# colors blue green red
#1 red;blue 1 0 1
#2 red;green 0 1 1
O usando base R
cbind(df, as.data.frame.matrix(table(stack(setNames(strsplit(df$colors, ";"),
seq_along(df$colors)))[2:1])))
En el código de OP, el strsplit
list
primer elemento[[1]]
) se selecciona en lugar de recorrer la lista, lo que resulta en el reciclaje del elemento y obtiene FALSE ya que no hay 'verde' en el primer list
elemento
library(purrr)
df %>%
mutate(green = map_int(strsplit(colors, ";"),
~ case_when('green' %in% .x ~ 1L, TRUE ~ 0L)))
# colors green
#1 red;blue 0
#2 red;green 1
Datos
colors <- c("red;blue", "red;green")
df <- data.frame(colors, stringsAsFactors = FALSE)
Código
cbind.data.frame(colors,
sapply( unique(unlist(strsplit( unlist(df), ";", fixed = TRUE))),
function(x) as.integer(grepl(x, colors))))
Producción
# colors red blue green
# 1 red;blue 1 1 0
# 2 red;green 1 0 1
Utilizando %in%
y sin expresión regular en un conjunto de datos diferente con elementos similares: verde y verdoso
colors <- c("red;blue;greenish", "red;green")
df <- data.frame(colors, stringsAsFactors = FALSE)
myfun <- function(x) unique(unlist(strsplit( unlist(x), ";", fixed = TRUE)))
df2 <- t(sapply( df$colors, function(x) as.integer(myfun(df) %in% myfun(x))))
colnames(df2) <- myfun(df)
df2
# red blue greenish green
# red;blue;greenish 1 1 1 0
# red;green 1 0 0 1
Reseñas y calificaciones del tutorial
Recuerda mostrar este artículo si lograste el éxito.