2015-07-03 11 views
5

Supponiamo che io ho il seguente frame di dati (quella attuale rappresenta molto grande insieme di dati)valori corrispondenti in base all'ID gruppo

df<- structure(list(x = c(1, 1, 1, 2, 2, 3, 3, 3), y = structure(c(1L, 
6L, NA, 2L, 4L, 3L, 7L, 5L), .Label = c("all", "fall", "hello", 
"hi", "me", "non", "you"), class = "factor"), z = structure(c(5L, 
NA, 4L, 2L, 1L, 6L, 3L, 4L), .Label = c("fall", "hi", "me", "mom", 
"non", "you"), class = "factor")), .Names = c("x", "y", "z"), row.names = c(NA, 
-8L), class = "data.frame") 

che si presenta come

>df 
    x  y z 
1 1 all non 
2 1 non <NA> 
3 1 <NA> mom 
4 2 fall hi 
5 2 hi fall 
6 3 hello you 
7 3 you me 
8 3 me mom 

Quello che sto cercando di fare è di conta il numero di valori corrispondenti in ciascun gruppo di x (1,2 o 3). Ad esempio, il numero di gruppo 1 ha un valore corrispondente che è "non" (il NA deve essere ignorato). L'output desiderato appare come:

x n 
1 1 1 
2 2 2 
3 3 2 

cercato di pensare a un modo di fare questo piuttosto che for-loop come ho un grande insieme di dati, ma non riusciva a trovare la mia strada attraverso.

risposta

5

utilizzando dplyr:

library(dplyr) 

df %>% group_by(x) %>% 
     summarise(n = sum(y %in% na.omit(z))) 
+0

Non proprio sicuro perché non mi dà l'output desiderato. Mi dà 'n 1 5' – athraa

+1

@AhmedSalhin Works per me. Forse 'plyr' sta interferendo. Penso che i pacchetti abbiano alcune incompatibilità, a seconda dell'ordine in cui sono caricati. – Frank

+0

@Frank Sì, hai ragione. Ho staccato 'plyr' e funziona per me. Sai come superare il problema interferente? – athraa

3

Ecco una soluzione che utilizza by() e match():

do.call(rbind,by(df,df$x,function(g) c(x=g$x[1],n=sum(!is.na(match(g$y,g$z,inc=NA)))))); 
## x n 
## 1 1 1 
## 2 2 2 
## 3 3 2 
+2

Mi piacciono queste soluzioni R di base ... onestamente, la mia è più lunga e maldestra, preferisco questa. Un voto! – SabDeM

4

Solo per divertimento notturno Ho cercato una soluzione R di base che ovviamente è brutto come l'inferno.

ind <- by(df, df$x, function(x) which(na.omit(x[["y"]]) %in% na.omit(df[["z"]]))) 
sm <- lapply(ind, length) 
cbind(unique(df$x), sm) 
sm 
1 1 1 
2 2 2 
3 3 2 

Un altro approccio R base, con meno codice (e con meno bruttezza spero):

ind <- by(df, df$x, function(x) sum(na.omit(x[["y"]]) %in% na.omit(x[["z"]]))) 
cbind(unique(df$x), ind) 
    ind 
1 1 1 
2 2 2 
3 3 2 
Problemi correlati