2014-10-17 44 views
2

我真的需要就如何解决问题的帮助。我有一个数据集,看起来像这样..选择与分组双类别数据从数据帧

Name Sex Total  
Anna F  10 
Jamie M  2 
Jamie F  7 
Mike M  13 
Sam F  6 
Sam M  3 

structure(list(Name = c("Anna", "Jamie", "Jamie", "Mike", "Sam", "Sam"), 
Sex = c("F", "M", "F", "M", "F", "M"), Total = c(10L, 2L, 7L, 13L, 6L, 3L)), 
.Names = c("Name", "Sex", "Total"), class = "data.frame", row.names = c(NA, -6L)) 

我想要做的就是让那些男性和女性名字的名字,所以结果看起来就像..

Name Sex Total 
Jamie M 2 
Jamie F 7 
Sam M 3 
Sam F 6 

但我真的很难接近它。

+0

类似,但多一点涉及的任务[这里](http://stackoverflow.com/questions/26347343/group-androgynous-names-and-sum-amount-for-each-year-in-a-data-frame-in-r)。 – ilir 2014-10-17 20:24:46

回答

2

您可以使用ave计算不同性别的每个名字的数量,只有那些子集那些具有两种性别。例如室内用样本数据

dd<-structure(list(Name = c("Anna", "Jamie", "Jamie", "Mike", "Sam", "Sam"), 
Sex = c("F", "M", "F", "M", "F", "M"), Total = c(10L, 2L, 7L, 13L, 6L, 3L)), 
.Names = c("Name", "Sex", "Total"), class = "data.frame", row.names = c(NA, -6L)) 

你可以做

both<-with(dd, ave(Sex, Name, FUN=function(x) length(unique(x))))=="2" 
dd[both, ] 

得到

Name Sex Total 
2 Jamie M  2 
3 Jamie F  7 
5 Sam F  6 
6 Sam M  3 

达到目标。

5

这是我会怎么处理它假设数据存储在d

# get a vector (set) of names that are use by both M and F 
dual.names <- intersect(d$Name[d$Sex=='M'], d$Name[d$Sex=='F']) 

# use set of dual names to filter data 
d[d$Name %in% dual.names, ] 
4

强制性Hadleyverse(dplyr & tidyr)答案:

library(tidyr) 
library(dplyr) 

dat %>% 
    spread(Sex, Total) %>% 
    filter(!is.na(M), !is.na(F)) %>% 
    gather(Sex, Total, M, F) %>% 
    arrange(Name) 

## Name Sex Total 
## 1 Jamie M  2 
## 2 Jamie F  7 
## 3 Sam M  3 
## 4 Sam F  6 

编辑MUCH更好dplyr通过@konvas的方法'评论:

dat %>% group_by(Name) %>% filter(length(unique(Sex)) == 2) 

编辑,并通过@大卫的意见进一步完善:

dat %>% group_by(Name) %>% filter(n_distinct(Sex) == 2) 

(我可以换乘点@konvas & @大卫? :-)

+2

我想你能避免传播和收集这样的'd%>%GROUP_BY(名称)%>%的过滤器(长度(唯一的(性别))== 2)' – konvas 2014-10-17 20:18:33

+0

@konvas这是'dplyr',扩散和聚集是一半的乐趣 – ilir 2014-10-17 20:20:00

+2

@ilir哈哈不够公平:) ..但如果OP的数据集较大,有显著的速度提升 – konvas 2014-10-17 20:20:45

2

加入晚了一点,但这里有一个data.table方法

library(data.table) 
setDT(df)[ , .SD[length(unique(Sex)) == 2], by = Name] 
##  Name Sex Total 
## 1: Jamie M  2 
## 2: Jamie F  7 
## 3: Sam F  6 
## 4: Sam M  3 

或者,如果你没有重复,这里有一个更快的解决方案

setDT(df)[ , .SD[.N == 2], by = Name]