Tengo una lista de empleados y necesito saber en qué departamento se encuentran con más frecuencia. Es trivial tabular la identificación del empleado con el nombre del departamento, pero es más complicado devolver el nombre del departamento, en lugar del número de recuentos de la lista, de la tabla de frecuencia. Un ejemplo simple a continuación (nombres de columna = departamentos, nombres de fila = ID de empleado).
DF <- matrix(sample(1:9,9),ncol=3,nrow=3)
DF <- as.data.frame.matrix(DF)
> DF
V1 V2 V3
1 2 7 9
2 8 3 6
3 1 5 4
Ahora como consigo
> DF2
RE
1 V3
2 V1
3 V2
Respuestas:
Una opción usando sus datos (para referencia futura, use
set.seed()
para hacer ejemplos usandosample
reproducibles):Una solución más rápida que usar
apply
podría sermax.col
:... donde
ties.method
puede estar cualquiera de"random"
"first"
o"last"
Esto, por supuesto, causa problemas si tiene dos columnas que son iguales al máximo. No estoy seguro de lo que quiere hacer en esa instancia, ya que tendrá más de un resultado para algunas filas. P.ej:
fuente
which.max
estará bien.apply
convierte eldata.frame
amatrix
internamente. Sin embargo, es posible que no vea una diferencia de rendimiento en estas dimensiones.colnames(DF)[max.col(replace(DF, cbind(seq_len(nrow(DF)), max.col(DF,ties.method="first")), -Inf), "first")]
Si está interesado en una
data.table
solución, aquí tiene una. Es un poco complicado ya que prefiere obtener la identificación para el primer máximo. Es mucho más fácil si prefiere el último máximo. Sin embargo, ¡no es tan complicado y es rápido!Aquí he generado datos de sus dimensiones (26746 * 18).
Datos
data.table
responder:Benchmarking:
Es aproximadamente 11 veces más rápido en datos de estas dimensiones y también
data.table
escala bastante bien.Editar: si alguno de los ID máximos está bien, entonces:
fuente
Una solución podría ser remodelar la fecha de amplia a larga colocando todos los departamentos en una columna y los recuentos en otra, agrupar por la identificación del empleador (en este caso, el número de fila) y luego filtrar a los departamentos con el valor máximo. También hay un par de opciones para manejar los vínculos con este enfoque.
fuente
Según las sugerencias anteriores, la siguiente
data.table
solución funcionó muy rápido para mí:Y también viene con la ventaja de que siempre se puede especificar qué columnas se
.SD
deben considerar mencionándolas en.SDcols
:En caso de que necesitemos el nombre de columna del valor más pequeño, como lo sugiere @lwshang, solo necesita usar
-.SD
:fuente
which.min
en algo que se vería así:DT[, MIN := colnames(.SD)[apply(.SD,1,which.min)]]
oDT[, MIN2 := colnames(.SD)[which.min(.SD)], by = 1:nrow(DT)]
en los datos ficticios de arriba. Esto no considera empates y devoluciones solo el primer mínimo. Tal vez considere hacer una pregunta separada. También tendría curiosidad por saber qué otras respuestas obtendría.colnames(.SD)[max.col(-.SD, ties.method="first")]
.Una
dplyr
solucion:Idea:
Código:
Resultado:
Este enfoque se puede ampliar fácilmente para obtener las
n
columnas superiores . Ejemplo paran=2
:Resultado:
fuente
Un
for
bucle simple también puede ser útil:fuente
Una opción de
dplyr 1.0.0
podría ser:Data de muestra:
fuente
Aquí hay una respuesta que funciona con data.table y es más simple. Esto asume que su data.table se llama
yourDF
:Reemplazar
("V1", "V2", "V3", "V4")
y(V1, V2, V3, V4)
con los nombres de sus columnasfuente