data matching/data 在长形数据库 r 中选择多个条件

data matching/data selection with multiple conditions in a long shaped database r

我已经为这个问题苦苦挣扎了一段时间,这是一个相当复杂的数据选择,有多种可能的输出,我找不到表达式来得到我想要的。 我正在测量一群鸟的离婚率。

可重现的数据库:

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 时,会放置越来越多的数字。显示每年相同的巢穴。 在连续 2 年中,我们有 5 种可能的情况(数字是巢 ID):

SAME PAIR 2014-2015: 1-6

EMPTY 2014-2015: 2-4-7

EMPTY 2014 but OCCUPIED 2015: 8

CHANGE OF PAIRS IN THE SAME NEST: 10

CHANGE OF ONE OF THE MEMBER OF THE PAIR: 3-9

UNKNOWN: 5

我追求的结果是:

在一起的对“2014-2015 年同一对”:2
其中一对改变了“改变一对成员之一”:2

我想出了如何计算保持在一起的对...

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

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

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

如果有什么不清楚的地方,我很乐意给出进一步的解释。我知道这是一个相当混乱的问题。

非常感谢, 祝一切顺利。

玩得开心

这是一种使用合并的方法。策略如下。首先将这些对分成 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。这些库非常适合数据操作。以下是 tidyr and dplyr 上的一些来源。如果您还有其他问题,请告诉我。

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)

没有包(即在 Base R 中)

如果你不想使用 dplyrtidyr 包你可以用这个基础替换前几行代码(直到调用 split 时) R 方法

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.

最后一段代码可能有点混乱。让我解释。为了确定一只鸟是否改变伙伴,我们识别重复项,因为一只鸟从一对移动到另一对会出现两次。然而,在很多年的情况下,鸟可以在几年中的任何一年中改变配对。要确定鸟类变化的正确年份,您需要使用上面的代码。我建议你构造一个函数来处理这种情况,因为涉及到相当多的输入。