studio seleccionar filtrar filas factores eliminar datos data contar r r-factor

seleccionar - En R, ¿cómo puedo acceder al primer elemento de cada nivel de un factor?



filtrar datos en r (7)

Tengo un marco de datos como este:

n = c(2, 2, 3, 3, 4, 4) n <- as.factor(n) s = c("a", "b", "c", "d", "e", "f") df = data.frame(n, s) df n s 1 2 a 2 2 b 3 3 c 4 3 d 5 4 e 6 4 f

y quiero acceder al primer elemento de cada nivel de mi factor (y tener en este ejemplo un vector que contiene a, c, e ).

Es posible alcanzar el primer elemento de un nivel, con

df$s[df$n == 2][1]

pero no funciona para todos los niveles:

df$s[df$n == levels(n)] [1] a f

¿Cómo lo harías tú?

Y para ir más lejos, me gustaría modificar mi marco de datos para ver cuál es el primer elemento para cada nivel en cada aparición. En mi ejemplo, una nueva columna debería ser:

n s rep firstelement 1 2 a a a 2 2 b c a 3 3 c e c 4 3 d a c 5 4 e c e 6 4 f e e


Aquí hay un enfoque utilizando el match :

df$s[match(levels(n), df$n)]

EDIT: Tal vez esto parece un poco confuso ...

Para obtener una columna que enumera los primeros elementos que podría usar, haga match dos veces (pero con x y table argumentos de la table intercambiados):

df$firstelement <- df$s[match(levels(n), df$n)[match(df$n, levels(n))]] df$firstelement # [1] a a c c e e # Levels: a b c d e f

Veamos esto en detalle:

## this returns the first matching elements match(levels(n), df$n) # [1] 1 3 5 ## when we swap the x and table argument in match we get the level index ## for each df$n (the duplicated indices are important) match(df$n, levels(n)) # [1] 1 1 2 2 3 3 ## results in c(1, 3, 5)[c(1, 1, 2, 2, 3, 3)] # [1] 1 1 3 3 5 5 df$s[c(1, 1, 3, 3, 5, 5)] # [1] a a c c e e # Levels: a b c d e f


En este caso, prefiero el paquete plyr, me da más libertad para manipular los datos.

library(plyr) ddply(df,.(n),function(subdf){return(subdf[1,])}) n s 1 2 a 2 3 c 3 4 e


La función ave es útil en estos casos:

df$firstelement = ave(df$s, df$n, FUN = function(x) x[1]) df n s firstelement 1 2 a a 2 2 b a 3 3 c c 4 3 d c 5 4 e e 6 4 f e


Sorprendido de no ver este clásico en la secuencia de respuestas todavía.

> do.call(rbind, lapply(split(df, df$n), function(x) x[1,])) ## n s ## 2 2 a ## 3 3 c ## 4 4 e


También podrías usar data.table.

library(data.table) dt = as.data.table(df) dt[, list(firstelement = s[1]), by=n]

lo que te llevaría:

n firstelement 1: 2 a 2: 3 c 3: 4 e

El bit by=n agrupa todo por cada valor de n por lo que s[1] está obteniendo el primer elemento de cada uno de esos grupos.

Para obtener esto como una columna extra podría hacer:

dt[, newcol := s[1], by=n] dt # n s newcol #1: 2 a a #2: 2 b a #3: 3 c c #4: 3 d c #5: 4 e e #6: 4 f e

Entonces, esto solo toma el valor de s de la primera fila de cada grupo y lo asigna a una nueva columna.


Editar La primera parte de mi respuesta aborda la pregunta original , es decir, antes de "Y para ir más allá" (que fue agregada por OP en una edición).

Otra posibilidad, utilizando duplicated . De ?duplicated : " duplicated() determina qué elementos de un vector o marco de datos son duplicados de elementos con subíndices más pequeños".

Aquí los usamos ! , la negación lógica (NO), para seleccionar elementos no duplicados de ''n'', es decir, primeros elementos de cada nivel de ''n''.

df[!duplicated(df$n), ] # n s # 1 2 a # 3 3 c # 5 4 e

Actualización No viste tu edición de "Y para ir más lejos" hasta ahora. Mi primera sugerencia sería definitivamente usar ave , como ya lo propusieron @thelatemail y @sparrow. Pero solo para indagar en la caja de herramientas de R y mostrarte una alternativa, aquí hay una dplyr sencilla:

Agrupe los datos por n , use la función de mutate para crear una nueva variable ''primero'', con el valor ''primer elemento de s'' ( s[1] ),

library(dplyr) df %.% group_by(n) %.% mutate( first = s[1]) # n s first # 1 2 a a # 2 2 b a # 3 3 c c # 4 3 d c # 5 4 e e # 6 4 f e

O vaya con las funciones de conveniencia de dplyr y use first lugar de [1] :

df %.% group_by(n) %.% mutate( first = first(s))

Una solución dplyr para su pregunta original sería utilizar summarise :

df %.% group_by(n) %.% summarise( first = first(s)) # n first # 1 2 a # 2 3 c # 3 4 e


df$s[sapply(levels(n), function(particular.level) { which(df$n == particular.level)[1]})]

Creo que su problema es que está comparando dos vectores df $ n es un vector y los niveles (n) son un vector. vector == el vector solo funciona para usted ya que df $ n es una longitud múltiple de niveles (n)