separate separar rnc por how dividir como comas caracteres r dataframe reshape data-manipulation strsplit

rnc - split separar por comas



Dividir cadenas delimitadas en una columna e insertar como nuevas filas (6)

Esta pregunta ya tiene una respuesta aquí:

Tengo un marco de datos de la siguiente manera:

+-----+-------+ | V1 | V2 | +-----+-------+ | 1 | a,b,c | | 2 | a,c | | 3 | b,d | | 4 | e,f | | . | . | +-----+-------+

Cada uno del alfabeto es un caracter separado por comas. Me gustaría dividir V2 en cada coma e insertar las cadenas divididas como nuevas filas. Por ejemplo, el resultado deseado será:

+----+----+ | V1 | V2 | +----+----+ | 1 | a | | 1 | b | | 1 | c | | 2 | a | | 2 | c | | 3 | b | | 3 | d | | 4 | e | | 4 | f | +----+----+

Estoy tratando de usar strsplit() para escupir V2 primero, luego lanzar la lista a un marco de datos. No funcionó. Cualquier ayuda será apreciada.


A partir de diciembre de 2014, esto se puede hacer utilizando la función Unnest del paquete tidyr de Hadley Wickham (ver notas de la versión http://blog.rstudio.org/2014/12/08/tidyr-0-2-0/ )

> library(tidyr) > library(dplyr) > mydf V1 V2 2 1 a,b,c 3 2 a,c 4 3 b,d 5 4 e,f 6 . . > mydf %>% mutate(V2 = strsplit(as.character(V2), ",")) %>% unnest(V2) V1 V2 1 1 a 2 1 b 3 1 c 4 2 a 5 2 c 6 3 b 7 3 d 8 4 e 9 4 f 10 . .

Actualización 2017: tenga en cuenta la función separate_rows como se describe por @Tif a continuación.

Funciona mucho mejor, y permite "unnest" columnas múltiples en una sola declaración:

> head(mydf) geneid chrom start end strand length gene_count ENSG00000223972.5 chr1;chr1;chr1;chr1;chr1;chr1;chr1;chr1;chr1 11869;12010;12179;12613;12613;12975;13221;13221;13453 12227;12057;12227;12721;12697;13052;13374;14409;13670 +;+;+;+;+;+;+;+;+ 1735 11 ENSG00000227232.5 chr1;chr1;chr1;chr1;chr1;chr1;chr1;chr1;chr1;chr1;chr1 14404;15005;15796;16607;16858;17233;17606;17915;18268;24738;29534 14501;15038;15947;16765;17055;17368;17742;18061;18366;24891;29570 -;-;-;-;-;-;-;-;-;-;- 1351 380 ENSG00000278267.1 chr1 17369 17436 - 68 14 ENSG00000243485.4 chr1;chr1;chr1;chr1;chr1 29554;30267;30564;30976;30976 30039;30667;30667;31097;31109 +;+;+;+;+ 1021 22 ENSG00000237613.2 chr1;chr1;chr1 34554;35277;35721 35174;35481;36081 -;-;- 1187 24 ENSG00000268020.3 chr1 52473 53312 + 840 14 > mydf %>% separate_rows(strand, chrom, gene_start, gene_end) geneid length gene_count strand chrom start end ENSG00000223972.5 1735 11 + chr1 11869 12227 ENSG00000223972.5 1735 11 + chr1 12010 12057 ENSG00000223972.5 1735 11 + chr1 12179 12227 ENSG00000223972.5 1735 11 + chr1 12613 12721 ENSG00000223972.5 1735 11 + chr1 12613 12697 ENSG00000223972.5 1735 11 + chr1 12975 13052 ENSG00000223972.5 1735 11 + chr1 13221 13374 ENSG00000223972.5 1735 11 + chr1 13221 14409 ENSG00000223972.5 1735 11 + chr1 13453 13670 ENSG00000227232.5 1351 380 - chr1 14404 14501 ENSG00000227232.5 1351 380 - chr1 15005 15038 ENSG00000227232.5 1351 380 - chr1 15796 15947 ENSG00000227232.5 1351 380 - chr1 16607 16765 ENSG00000227232.5 1351 380 - chr1 16858 17055 ENSG00000227232.5 1351 380 - chr1 17233 17368 ENSG00000227232.5 1351 380 - chr1 17606 17742 ENSG00000227232.5 1351 380 - chr1 17915 18061 ENSG00000227232.5 1351 380 - chr1 18268 18366 ENSG00000227232.5 1351 380 - chr1 24738 24891 ENSG00000227232.5 1351 380 - chr1 29534 29570 ENSG00000278267.1 68 5 - chr1 17369 17436 ENSG00000243485.4 1021 8 + chr1 29554 30039 ENSG00000243485.4 1021 8 + chr1 30267 30667 ENSG00000243485.4 1021 8 + chr1 30564 30667 ENSG00000243485.4 1021 8 + chr1 30976 31097 ENSG00000243485.4 1021 8 + chr1 30976 31109 ENSG00000237613.2 1187 24 - chr1 34554 35174 ENSG00000237613.2 1187 24 - chr1 35277 35481 ENSG00000237613.2 1187 24 - chr1 35721 36081 ENSG00000268020.3 840 0 + chr1 52473 53312


Ahora puede usar tidyr 0.5.0''s separate_rows está en lugar de strsplit + unnest .

Por ejemplo:

library(tidyr) (df <- read.table(textConnection("1|a,b,c/n2|a,c/n3|b,d/n4|e,f"), header = F, sep = "|", stringsAsFactors = F))

V1 V2 1 1 a,b,c 2 2 a,c 3 3 b,d 4 4 e,f

separate_rows(df, V2)

Da:

V1 V2 1 1 a 2 1 b 3 1 c 4 2 a 5 2 c 6 3 b 7 3 d 8 4 e 9 4 f

Ver referencia: https://blog.rstudio.org/2016/06/13/tidyr-0-5-0/


Aquí hay otra forma de hacerlo ...

df <- read.table(textConnection("1|a,b,c/n2|a,c/n3|b,d/n4|e,f"), header = F, sep = "|", stringsAsFactors = F) df ## V1 V2 ## 1 1 a,b,c ## 2 2 a,c ## 3 3 b,d ## 4 4 e,f s <- strsplit(df$V2, split = ",") data.frame(V1 = rep(df$V1, sapply(s, length)), V2 = unlist(s)) ## V1 V2 ## 1 1 a ## 2 1 b ## 3 1 c ## 4 2 a ## 5 2 c ## 6 3 b ## 7 3 d ## 8 4 e ## 9 4 f


Aquí hay una solución data.table :

d.df <- read.table(header=T, text="V1 | V2 1 | a,b,c 2 | a,c 3 | b,d 4 | e,f", stringsAsFactors=F, sep="|", strip.white = TRUE) require(data.table) d.dt <- data.table(d.df, key="V1") out <- d.dt[, list(V2 = unlist(strsplit(V2, ","))), by=V1] # V1 V2 # 1: 1 a # 2: 1 b # 3: 1 c # 4: 2 a # 5: 2 c # 6: 3 b # 7: 3 d # 8: 4 e # 9: 4 f > sapply(out$V2, nchar) # (or simply nchar(out$V2)) # a b c a c b d e f # 1 1 1 1 1 1 1 1 1


Otra solución data.table , que no depende de la existencia de campos únicos en los datos originales.

DT = data.table(read.table(header=T, text="blah | splitme T | a,b,c T | a,c F | b,d F | e,f", stringsAsFactors=F, sep="|", strip.white = TRUE)) DT[,.( blah , splitme , splitted=unlist(strsplit(splitme, ",")) ),by=seq_len(nrow(DT))]

Lo importante es by=seq_len(nrow(DT)) , este es el by=seq_len(nrow(DT)) ''falso'' en el que se produce la división. Es tentador usar by=.I lugar, ya que debe definirse de la misma manera, pero .I Parece ser una cosa mágica que cambia su valor, mejor para seguir con by=seq_len(nrow(DT))

Hay tres columnas en la salida. Simplemente nombramos las dos columnas existentes y luego calculamos la tercera como una división

.( blah # first column of original , splitme # second column of original , splitted = unlist(strsplit(splitme, ",")) )


Puedes considerar cSplit con direction = "long" desde mi paquete "splitstackshape".

El uso sería:

cSplit(mydf, "V2", ",", "long") ## V1 V2 ## 1: 1 a ## 2: 1 b ## 3: 1 c ## 4: 2 a ## 5: 2 c ## 6: 3 b ## 7: 3 d ## 8: 4 e ## 9: 4 f

Vieja respuesta ...

Aquí hay un enfoque que usa la base R. Supone que estamos comenzando con un data.frame llamado "mydf". Utiliza read.csv para leer en la segunda columna como un data.frame separado, que combinamos con la primera columna de sus datos de origen. Finalmente, usa reshape para convertir los datos en una forma larga.

temp <- data.frame(Ind = mydf$V1, read.csv(text = as.character(mydf$V2), header = FALSE)) temp1 <- reshape(temp, direction = "long", idvar = "Ind", timevar = "time", varying = 2:ncol(temp), sep = "") temp1[!temp1$V == "", c("Ind", "V")] # Ind V # 1.1 1 a # 2.1 2 a # 3.1 3 b # 4.1 4 e # 1.2 1 b # 2.2 2 c # 3.2 3 d # 4.2 4 f # 1.3 1 c

Otra alternativa bastante directa es:

stack( setNames( sapply(strsplit(mydf$V2, ","), function(x) gsub("^//s|//s$", "", x)), mydf$V1)) values ind 1 a 1 2 b 1 3 c 1 4 a 2 5 c 2 6 b 3 7 d 3 8 e 4 9 f 4