长形数据库中具有多个条件的数据匹配/数据选择r

时间:2016-02-05 18:37:12

标签: r dataset selection

我一直在努力解决这个问题,这是一个相当复杂的数据选择,有多个可能的输出,我找不到表达式来得到我想要的东西。 我正在测量一群鸟类的离婚率。

可重现的数据库:

nest<- rep(seq(1:10),2)
year<- c(rep(2014, 10), rep(2015, 10))
pair<- c("TH4327_TH4317", "2", "TH8522_T75390" ,"4", "TJ1704_TJ1703", "TH4335_TH4333",
         "7", "8", "TH4337_TH4323", "T74703_TH1797",
         "TH4327_TH4317", "12", "TH8522_T75550","14", "TJ1704_NA" , "TH4335_TH4333",           "17", "TH8715_TH8714", "TH4388_TH4323", "TE9639_TH9675")
test<- data.frame(nest, year, pair)
test$pair <- as.character(test$pair)
test$year <- as.character(test$year)

下划线分隔一对中2个成员的ID。如果没有ID,则会增加数量。显示每年相同的巢。 在连续两年中,我们有5种可能的场景(数字是嵌套ID):

  

同上2014 - 2015年:1-6

     

2014-2015 EMPTY:2-4-7

     

2014年EMPTY,但2015年被占领:8

     

同一巢中对的变化:10

     

改变一对成员:3-9

     

未知:5

我追求的结果是:

保持在一起的对“相同的2014-2015”:2 成对的一对改变了“改变一对成员”:2

我想到了如何计算在一起的对......

same<-test$pair[test$year=="2014"] %in% test$pair[test$year=="2015"]
table(same)

但是我无法获得有关离婚对的信息。

我尝试了几个命令whichifelse,但没有成功。

如果不清楚,我很乐意给出进一步的解释。我知道这是一个非常混乱的问题。

非常感谢, 一切顺利。

玩得开心

1 个答案:

答案 0 :(得分:1)

这是一种使用合并的方法。策略如下。首先将对分为p1p2(我使用tidyr::separate执行此操作)。然后我将数据按年分组,并使用p1作为唯一标识符进行合并。这意味着现在将有两个不同的p2,一个用于2014年,一个用于2015.现在可以直接测试群体是否在一起或离婚。

如果你有多年,这种方法需要概括。如果需要,我很乐意提供这样的概括。

library(tidyr)

test <- 
test %>%
  filter(nchar(test$pair) > 3) %>% #getting rid of missing pairs
  separate(pair, c("p1", "p2"), "_") %>%
  select(-nest) #getting rid of nest which is superfluous 

test <- merge(test[test$year=="2014",], test[test$year=="2015",], by = "p1", all = TRUE)

#Same group across 2014 and 2015
na.omit(test[test$p2.x == test$p2.y, grep("p", names(test))])

#Different Group across 2014 and 2015
na.omit(test[test$p2.x != test$p2.y, grep("p", names(test))])

更新

要概括代码多年,请使用以下代码。这是一种比循环更好的方法。另请注意,上面的代码不起作用,因为我忘了包含dplyr库。请务必下载并加载dplyrtidyr。这些库非常适合数据操作。以下是tidyrdplyr的一些来源。如果您还有其他问题,请告诉我。

library(tidyr)
library(dplyr)

test <- 
test %>%
  filter(nchar(test$pair) > 3) %>% #getting rid of missing pairs
  separate(pair, c("p1", "p2"), "_") %>% #splitting pairs
  select(-nest) #getting rid of nest which is superfluous 

test <- split(test, test$year) #split data into lists by year
test <- Map(function(d, n){names(d)[grepl("p2", names(d))] <- paste("p2", n, sep = "_"); d}, d = test, n = names(test)) #this line can be omitted.  It simply insures that your final data set looks nice.
test <- Reduce(function(...) merge(..., by = "p1", all = TRUE), test)

没有包裹(即在基地R中)

如果您不想使用dplyrtidyr软件包,则可以使用此基本R方法替换前几行代码(直到调用split为止)

test <- test[nchar(test$pair) > 3, !names(test)%in%"nest"]

split_pair <- do.call(rbind, strsplit(test$pair, "_"))

test$p1 <- split_pair[, 1]
test$p2 <- split_pair[, 2]
test <- test[, !names(test)%in%"pair"]

最终更新......希望

玩得开心在下面的评论中提出了一个很好的观点。由于我使用p1作为唯一标识符,因此无法识别p2何时更改。为了克服这个问题,我做了以下几点......

 test <- split(test, test$year) #split data into lists by year

 test <- Reduce(function(...) merge(..., by = c("p1", "p2"), all = TRUE), test) #merge on both p1 and p2 to overcome the previous problem.  Pair are now unique identifiers

#Stayed in same relationship
stay = test$year.x == "2014" & test$year.y == "2015"
na.omit(test[stay, ])

#p1 changes couples between year.x and year.y
tp1 <- test[test$p1 %in% test[duplicated(test$p1), "p1"], c("p1", "p2", "year.x", "year.y")]
is_na <- (is.na(tp1$year.x) & is.na(tp1$year.y))
stay_tp1 <- tp1$year.x == "2014" & tp1$year.y == "2015"
stay_tp1[is.na(stay_tp1)] <- FALSE
tp1 <- tp1[!(stay_tp1 | is_na), ]

#A similar approach works for p2.  Notice it is probably best to do this in a function.  If you do use a function remember you will need to pass your variables as strings, unless you want to use NSE.

代码的最后一点可能有点令人困惑。让我解释。为了确定鸟是否改变了伙伴,我们识别重复,因为从一对移动到另一对的鸟将出现两次。然而,在多年的情况下,鸟类可以在几年中的任何一年中改变对。要确定鸟类更改的正确年份,您需要使用上述代码。我建议你构建一个函数来处理这种情况,因为涉及到相当多的类型。