Tengo un montón de columnas en un marco de datos que quiero pegar juntas (separadas por "-") de la siguiente manera:
data <- data.frame('a' = 1:3,
'b' = c('a','b','c'),
'c' = c('d', 'e', 'f'),
'd' = c('g', 'h', 'i'))
i.e.
a b c d
1 a d g
2 b e h
3 c f i
En el que quiero convertirme:
a x
1 a-d-g
2 b-e-h
3 c-f-i
Normalmente podría hacer esto con:
within(data, x <- paste(b,c,d,sep='-'))
y luego eliminar las columnas antiguas, pero desafortunadamente no sé los nombres de las columnas específicamente, solo un nombre colectivo para todas las columnas, por ejemplo, sabría que cols <- c('b','c','d')
¿Alguien sabe una forma de hacer esto?
do.call
?evil(parse(...))
, por ejemplo , pero creo quedo.call
es la llamada correcta aquí.collapse = "-"
? apaste
?Como una variante de la respuesta de baptiste , con
data
definido como tiene y las columnas que desea juntar definidas encols
Puede agregar la nueva columna
data
y eliminar las antiguas conlo que da
fuente
data.frame
vector con un solo carácter será una indexación de columna, a pesar de que el primer argumento suele ser el índice de fila.Con el
tidyr
paquete, esto se puede manejar fácilmente en 1 llamada de función.Editar: excluir la primera columna, todo lo demás se pega.
fuente
within(data, x <- paste(b,c,d,sep='-'))
como lo ilustraron.unite_(data, "b_c_d", cols)
que, o dependiendo de su data.frame real, tambiénunite(data, b_c_d, -a)
podría ser un candidato.Construiría un nuevo data.frame:
fuente
d[ , cols]
usted, es posible que desee utilizard[ , names(d) != 'a']
si todos menos laa
columna se van a pegar juntos.cbind(a = d['a'], x = do.call(paste, c(d[cols], sep = '-')))
, por ejemplo, evitar las comas,list
ydata.frame
mientras usa eldata.frame
método decbind
Solo para agregar una solución adicional con la
Reduce
que probablemente sea más lentado.call
pero probadamente mejor queapply
porque evitará lamatrix
conversión. Además, en su lugar, unfor
bucle que podríamos usarsetdiff
para eliminar columnas no deseadasAlternativamente, podríamos actualizar
data
en su lugar usando eldata.table
paquete (asumiendo datos nuevos)Otra opción es usar en
.SDcols
lugar demget
como enfuente
Comparé las respuestas de Anthony Damico, Brian Diggs y data_steve en una pequeña muestra
tbl_df
y obtuve los siguientes resultados.Sin embargo, cuando evalué por mi cuenta
tbl_df
con ~ 1 millón de filas y 10 columnas, los resultados fueron bastante diferentes.fuente
En mi opinión, la
sprintf
función-merece un lugar entre estas respuestas también. Puede usarlo de lasprintf
siguiente manera:lo que da:
Y para crear el marco de datos requerido:
dando:
Aunque
sprintf
no tiene una clara ventaja sobre la combinacióndo.call
/paste
de @BrianDiggs, es especialmente útil cuando también desea rellenar ciertas partes de la cadena deseada o cuando desea especificar el número de dígitos. Consulte?sprintf
las diversas opciones.Otra variante sería utilizar
pmap
deronroneo:Nota: esta
pmap
solución solo funciona cuando las columnas no son factores.Un punto de referencia en un conjunto de datos más grande:
resulta en:
Datos usados:
fuente
Aquí hay un enfoque bastante poco convencional (pero rápido): use
fwrite
fromdata.table
para "pegar" las columnas juntas yfread
volver a leerlas. Por conveniencia, escribí los pasos como una función llamadafpaste
:He aquí un ejemplo:
¿Cómo funciona?
fuente
TMPDIR=/dev/shm R
) pero no noto una gran diferencia en comparación con estos resultados. Tampoco he jugado en absoluto con la cantidad de hilos utilizados parafread
ofwrite
para ver cómo afecta los resultados.fuente
Sé que esta es una pregunta antigua, pero pensé que de todos modos debería presentar la solución simple usando la función paste () como lo sugirió el interlocutor:
fuente