2016-09-22 19 views
1

我已经搜索了一段时间的这个问题的答案并没有找到这个确切的测试用例。如果在别处解决了,请接受我的道歉。使用dplyr对多个行和列匹配的数据框进行子集设置

我有一个来自政府调查计划的大型数据框data生物观察(约2,500,000行,约50列)。重要的专栏是(调查的)reg(地区),speciesyear

我想将数据框的子集包含在每个区域只包含每年至少发现一次的物种。 (我也需要这样做,对于每年至少发现10次的物种,但我认为解决方案是相同的。)

换句话说,我只需要筛选出species所在的行每年region也存在 - 实质上,所有行unique(year)每个species匹配unique(year)每个reg。 (只有9个区域,所以我肯定可以将数据分为9个数据帧,并重复9次过滤,但我希望只有dplyr更优雅的解决方案,我可以直接应用到data。)

谢谢!

编辑:我创建了@aichao建议的模拟数据集。

> year = c(1999,2000,2000,2004,2004,2008) 
> reg = c('ai','ci','ci','ai','ai','ci') 
> species = c('blueei','greenei','yellowei','blueei','greenei','yellowei') 
> df <- data.frame(year, reg, species) 
> df 
    year reg species 
1 1999 ai blueei 
2 2000 ci greenei 
3 2000 ci yellowei 
4 2004 ai blueei 
5 2004 ai greenei 
6 2008 ci yellowei 

所以在这种自由度,我想只保留所发现的每一个区域进行了调查时间物种(让我们假装这是一个完整的数据)。从ai开始,我想保留blueei - 这是在每个调查年份发现的 - 但不是greenei。同样,在ci,我想保持yellowei但不greenei,因为greenei没有在2008年

+0

请提交最小exampe用'dput(数据)'或数据帧 –

+0

@Alexa的一个子集,欢迎来到SO。这将有助于脂肪酶回答你的问题,如果他们有你的数据样本 - http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example – Bulat

回答

0

您可以创建自己的原始数据帧的id变量代表区+物种对。

year = c(1999,2000,2000,2004,2004,2008) 
reg = c('ai','ci','ci','ai','ai','ci') 
species = c('blueei','greenei','yellowei','blueei','greenei','yellowei') 

df <- data.frame(year, reg, species) %>% 
mutate(ids = paste(reg, species, sep='-')) 

然后创建标识一个新的数据帧,对于每个region,的year S,year s各自species多少存在,并且其种类存在于所有年总数。

df2 <- df %>% 
group_by(reg) %>% 
mutate(n_yrs = length(unique(year))) %>% 
group_by(reg, ids) %>% 
summarize(present_yrs = length(unique(year)), 
     all_yrs  = mean(n_yrs, na.rm = T)) %>% 
filter(present_yrs == all_yrs) 

最后,过滤你的旧数据集只包括id的在df2

filter(df, ids %in% df2$ids) 
0

露面只保留所发现的每一个区域进行了调查

时间的物种,我们可以做到使用dplyr如下:

library(dplyr) 
result <- df %>% group_by(reg) %>% mutate(num.years.in.reg = length(unique(year))) %>% 
       group_by(reg,species) %>% filter(length(unique(year)) == first(num.years.in.reg)) %>% 
       select(-num.years.in.reg) %>% arrange(reg) 

注:

  1. 首先,group_byreg并创建一个列num.years.in.reg,该地区被调查的数量为unique年。
  2. 然后,group_byregspecies,只保留那些species针对该species在该地区被调查的unique年数等于unique年该地区被调查的数量。这里,first只是从num.years.in.reg中检索第一个值,因为它们对于组中的所有行都是相同的。
  3. 删除num.years.in.reg列并按regresult进行排序。
  4. 请注意,在过滤逻辑中,我们不需要比较唯一的年份值,只是唯一年份的数量,因为第二个分组是第一个分组的子集。也就是说,独一无二的年份将是相同的,但在第二次分组中可能比第一次少。

随着您发布的数据,该result是:

print(result) 
##Source: local data frame [4 x 3] 
##Groups: reg, species [2] 
## 
## year reg species 
## <dbl> <chr> <chr> 
##1 1999 ai blueei 
##2 2004 ai blueei 
##3 2000 ci yellowei 
##4 2008 ci yellowei 
+0

非常感谢帮助,@aichao。对不起,我没有以更有用的格式发布数据。 我试图找出一个地区所有年份中存在的物种。因此,如果一个地区在12年内取样,我只想对这12年中每个地区都取样的物种进行分类。不过,这一点因地区而异 - 它们的采样方式都不相同。我不确定'filter(n()> 1)是干什么的 - 它能完成那个吗? – AFH

+0

@Alexa:对于迟到的回复感到抱歉。例如,通过将'year','reg'和'species'分组,我们划分数据,使得每个组具有('''','reg','species')值的唯一三元组, 2010','ai','greenei')。现在,每个组可能只有一行数据或可能有多行。所有'filter(n()> 1)'都只保留那些组中有多行的组。这是我对你想要什么的解释,但我可能是错的。请告诉我。 – aichao

+0

哦,现在我明白了。谢谢!这不是我想要的。在上面的示例数据框中,我实际上想要保留所有这些行。我试图保留区域调查中每年发现的所有物种,但该区域已经进行了多年调查。因此,如果“ai”仅在2010年进行调查,我会保留2010年发现的所有物种。如果在2010年,2011年和2012年对“ci”进行调查,我只想保留每个调查年份的物种 - 2010年,2011年和2012年。我将用另一个更有用的模拟df重新编辑原始问题。 – AFH

相关问题