varias superponer studio modificar lineas graficos graficas ejes r string dataframe split r-faq

studio - superponer graficas en r



Divida una columna de un marco de datos en varias columnas (15)

5 años más tarde agregando la solución obligatoria data.table

library(data.table) ## v 1.9.6+ setDT(before)[, paste0("type", 1:2) := tstrsplit(type, "_and_")] before # attr type type1 type2 # 1: 1 foo_and_bar foo bar # 2: 30 foo_and_bar_2 foo bar_2 # 3: 4 foo_and_bar foo bar # 4: 6 foo_and_bar_2 foo bar_2

También podríamos asegurarnos de que las columnas resultantes tengan los tipos correctos y mejoren el rendimiento agregando type.convert y argumentos fixed (ya que "_and_" no es realmente una expresión regular)

setDT(before)[, paste0("type", 1:2) := tstrsplit(type, "_and_", type.convert = TRUE, fixed = TRUE)]

Me gustaría tomar datos del formulario

before = data.frame(attr = c(1,30,4,6), type=c(''foo_and_bar'',''foo_and_bar_2'')) attr type 1 1 foo_and_bar 2 30 foo_and_bar_2 3 4 foo_and_bar 4 6 foo_and_bar_2

y use split() en la columna " type " de arriba para obtener algo como esto:

attr type_1 type_2 1 1 foo bar 2 30 foo bar_2 3 4 foo bar 4 6 foo bar_2

Se me ocurrió algo increíblemente complejo que implicaba alguna forma de apply que funcionó, pero desde entonces he extraviado eso. Parecía demasiado complicado para ser la mejor manera. Puedo usar strsplit como a continuación, pero luego no veo cómo volver a ponerlo en 2 columnas en el marco de datos.

> strsplit(as.character(before$type),''_and_'') [[1]] [1] "foo" "bar" [[2]] [1] "foo" "bar_2" [[3]] [1] "foo" "bar" [[4]] [1] "foo" "bar_2"

Gracias por cualquier puntero. Todavía no he comido completamente las listas de R.


Aquí hay un revestimiento base R one que se superpone a varias soluciones anteriores, pero devuelve un data.frame con los nombres propios.

out <- setNames(data.frame(before$attr, do.call(rbind, strsplit(as.character(before$type), split="_and_"))), c("attr", paste0("type_", 1:2))) out attr type_1 type_2 1 1 foo bar 2 30 foo bar_2 3 4 foo bar 4 6 foo bar_2

Utiliza strsplit para dividir la variable y data.frame con do.call / rbind para volver a poner los datos en un data.frame. La mejora incremental adicional es el uso de setNames para agregar nombres de variables al data.frame.


Desde la versión R 3.4.0, puede usar strcapture() desde el paquete utils (incluido con las instalaciones base R), vinculando el resultado a la (s) otra (s) columna (s).

out <- strcapture( "(.*)_and_(.*)", as.character(before$type), data.frame(type_1 = character(), type_2 = character()) ) cbind(before["attr"], out) # attr type_1 type_2 # 1 1 foo bar # 2 30 foo bar_2 # 3 4 foo bar # 4 6 foo bar_2


El tema está casi agotado, pero me gustaría ofrecer una solución a una versión un poco más general en la que no se conoce el número de columnas de salida, a priori. Entonces, por ejemplo, tienes

before = data.frame(attr = c(1,30,4,6), type=c(''foo_and_bar'',''foo_and_bar_2'', ''foo_and_bar_2_and_bar_3'', ''foo_and_bar'')) attr type 1 1 foo_and_bar 2 30 foo_and_bar_2 3 4 foo_and_bar_2_and_bar_3 4 6 foo_and_bar

No podemos usar dplyr separate() porque no conocemos el número de columnas de resultados antes de la división, entonces he creado una función que usa stringr para dividir una columna, dado el patrón y un prefijo de nombre para el generado columnas Espero que los patrones de codificación utilizados sean correctos.

split_into_multiple <- function(column, pattern = ", ", into_prefix){ cols <- str_split_fixed(column, pattern, n = Inf) # Sub out the ""''s returned by filling the matrix to the right, with NAs which are useful cols[which(cols == "")] <- NA cols <- as.tibble(cols) # name the ''cols'' tibble as ''into_prefix_1'', ''into_prefix_2'', ..., ''into_prefix_m'' # where m = # columns of ''cols'' m <- dim(cols)[2] names(cols) <- paste(into_prefix, 1:m, sep = "_") return(cols) }

Entonces podemos usar split_into_multiple en una tubería dplyr de la siguiente manera:

after <- before %>% bind_cols(split_into_multiple(.$type, "_and_", "type")) %>% # selecting those that start with ''type_'' will remove the original ''type'' column select(attr, starts_with("type_")) >after attr type_1 type_2 type_3 1 1 foo bar <NA> 2 30 foo bar_2 <NA> 3 4 foo bar_2 bar_3 4 6 foo bar <NA>

Y luego podemos usar gather para poner en orden ...

after %>% gather(key, val, -attr, na.rm = T) attr key val 1 1 type_1 foo 2 30 type_1 foo 3 4 type_1 foo 4 6 type_1 foo 5 1 type_2 bar 6 30 type_2 bar_2 7 4 type_2 bar_2 8 6 type_2 bar 11 4 type_3 bar_3


Esta pregunta es bastante antigua, pero añadiré que la solución que encontré es la más simple en la actualidad.

library(reshape2) before = data.frame(attr = c(1,30,4,6), type=c(''foo_and_bar'',''foo_and_bar_2'')) newColNames <- c("type1", "type2") newCols <- colsplit(before$type, "_and_", newColNames) after <- cbind(before, newCols) after$type <- NULL after


Otra opción es usar el nuevo paquete tidyr.

library(dplyr) library(tidyr) before <- data.frame( attr = c(1, 30 ,4 ,6 ), type = c(''foo_and_bar'', ''foo_and_bar_2'') ) before %>% separate(type, c("foo", "bar"), "_and_") ## attr foo bar ## 1 1 foo bar ## 2 30 foo bar_2 ## 3 4 foo bar ## 4 6 foo bar_2


Otro enfoque más: use rbind on out :

before <- data.frame(attr = c(1,30,4,6), type=c(''foo_and_bar'',''foo_and_bar_2'')) out <- strsplit(as.character(before$type),''_and_'') do.call(rbind, out) [,1] [,2] [1,] "foo" "bar" [2,] "foo" "bar_2" [3,] "foo" "bar" [4,] "foo" "bar_2"

Y para combinar:

data.frame(before$attr, do.call(rbind, out))


Otro enfoque si desea seguir con strsplit() es usar el unlist() . Aquí hay una solución en ese sentido.

tmp <- matrix(unlist(strsplit(as.character(before$type), ''_and_'')), ncol=2, byrow=TRUE) after <- cbind(before$attr, as.data.frame(tmp)) names(after) <- c("attr", "type_1", "type_2")


Para agregar a las opciones, también podría usar mi función splitstackshape::cSplit como esta:

library(splitstackshape) cSplit(before, "type", "_and_") # attr type_1 type_2 # 1: 1 foo bar # 2: 30 foo bar_2 # 3: 4 foo bar # 4: 6 foo bar_2


Tenga en cuenta que sapply con "[" se puede usar para extraer el primer elemento o el segundo elemento en esas listas de modo que:

before$type_1 <- sapply(strsplit(as.character(before$type),''_and_''), "[", 1) before$type_2 <- sapply(strsplit(as.character(before$type),''_and_''), "[", 2) before$type <- NULL

Y aquí hay un método gsub:

before$type_1 <- gsub("_and_.+$", "", before$type) before$type_2 <- gsub("^.+_and_", "", before$type) before$type <- NULL


Una manera fácil es usar sapply() y la [ función:

before <- data.frame(attr = c(1,30,4,6), type=c(''foo_and_bar'',''foo_and_bar_2'')) out <- strsplit(as.character(before$type),''_and_'')

Por ejemplo:

> data.frame(t(sapply(out, `[`))) X1 X2 1 foo bar 2 foo bar_2 3 foo bar 4 foo bar_2

sapply() es una matriz y necesita transposición y conversión a un marco de datos. Es entonces algunas manipulaciones simples que producen el resultado que deseaba:

after <- with(before, data.frame(attr = attr)) after <- cbind(after, data.frame(t(sapply(out, `[`)))) names(after)[2:3] <- paste("type", 1:2, sep = "_")

En este punto, after es lo que querías

> after attr type_1 type_2 1 1 foo bar 2 30 foo bar_2 3 4 foo bar 4 6 foo bar_2


Utilice stringr::str_split_fixed

library(stringr) str_split_fixed(before$type, "_and_", 2)


aquí hay un trazador de líneas en la misma línea que la solución de aniko, pero utilizando el paquete stringr de hadley:

do.call(rbind, str_split(before$type, ''_and_''))


base pero probablemente lenta:

n <- 1 for(i in strsplit(as.character(before$type),''_and_'')){ before[n, ''type_1''] <- i[[1]] before[n, ''type_2''] <- i[[2]] n <- n + 1 } ## attr type type_1 type_2 ## 1 1 foo_and_bar foo bar ## 2 30 foo_and_bar_2 foo bar_2 ## 3 4 foo_and_bar foo bar ## 4 6 foo_and_bar_2 foo bar_2


tp <- c("a-c","d-e-f","g-h-i","m-n") temp = strsplit(as.character(tp),''-'') x=c(); y=c(); z=c(); #tab=data.frame() #tab= cbind(tab,c(x,y,z)) for(i in 1:length(temp) ) { l = length(temp[[i]]); if(l==2) { x=c(x,temp[[i]][1]); y=c(y,"NA") z=c(z,temp[[i]][2]); df= as.data.frame(cbind(x,y,z)) }else { x=c(x,temp[[i]][1]); y=c(y,temp[[i]][2]); z=c(z,temp[[i]][3]); df= as.data.frame(cbind(x,y,z)) } }