我一直在努力解决这个问题,这是一个相当复杂的数据选择,有多个可能的输出,我找不到表达式来得到我想要的东西。 我正在测量一群鸟类的离婚率。
可重现的数据库:
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)
但是我无法获得有关离婚对的信息。
我尝试了几个命令which
和ifelse
,但没有成功。
如果不清楚,我很乐意给出进一步的解释。我知道这是一个非常混乱的问题。
非常感谢, 一切顺利。
玩得开心
答案 0 :(得分:1)
这是一种使用合并的方法。策略如下。首先将对分为p1
和p2
(我使用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
库。请务必下载并加载dplyr
和tidyr
。这些库非常适合数据操作。以下是tidyr和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)
如果您不想使用dplyr
和tidyr
软件包,则可以使用此基本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.
代码的最后一点可能有点令人困惑。让我解释。为了确定鸟是否改变了伙伴,我们识别重复,因为从一对移动到另一对的鸟将出现两次。然而,在多年的情况下,鸟类可以在几年中的任何一年中改变对。要确定鸟类更改的正确年份,您需要使用上述代码。我建议你构建一个函数来处理这种情况,因为涉及到相当多的类型。