2015-07-03 2 views
5

Предположим, что у меня есть следующие кадр данных (фактическая один представляет очень большой набор данных)значения Matching на основе идентификатора группы

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") 

который выглядит как

>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 

То, что я пытаюсь сделать, это подсчитайте количество согласованных значений в каждой группе из x (1,2 или 3). Например, номер группы 1 имеет одно согласованное значение, которое равно "non" (NA следует игнорировать). Желаемый результат выглядит следующим образом:

x n 
1 1 1 
2 2 2 
3 3 2 

Пытался думать способ сделать это, а не for-loop, как у меня есть большой набор данных, но не мог найти свой путь до конца.

ответ

5

использованием dplyr:

library(dplyr) 

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

Не совсем уверен, почему он не дает мне желаемый результат. Это дает мне «n 1 5' – athraa

+1

@AhmedSalhin Работает для меня. Может быть, 'plyr' вмешивается. Я думаю, что у пакетов есть некоторые несовместимости, в зависимости от того, в каком порядке они загружены. – Frank

+0

@Frank Да, вы правы. Я отделил «plyr», и он работает для меня. Вы знаете, как преодолеть мешающую проблему? – athraa

3

Вот решение с использованием by() и 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

Мне нравятся эта база R решений ... честно, мой длинный и неуклюжий, я предпочитаю этот. Голосовать! – SabDeM

4

Только для ночных развлечений я попробовал решение базового R, который, конечно, некрасиво, как ад.

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 

Другой базовый R подход, с меньшим количеством кода (и с меньшим уродства я надеюсь):

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 
Смежные вопросы