同时将%in%用于多个条件

时间:2018-08-15 10:38:53

标签: r

我有一个数据框,其中显示了一些有关个人(ID)的数据,他们生活的每一年都有一行。它还包含有关父母ID(P.ID)和出生时父母年龄(P.AB)的信息。

# Dataframe A: 1 row per individual
dfA <- data.frame(
  "ID"   = c("A", "B", "C", "D", "E"), 
  "P.ID" = c(NA,  "A", "A", "B", "B"), 
  "P.AB" = c(NA, 3, 4, 2, 4),
  "LS" = c(5, 6, 3, 4, 5))

# Dataframe B: 1 row per year of life
dfB <- data.frame("ID" = rep(dfA[,'ID'], dfA[,'LS']+1))
dfB <- merge(dfB, dfA, by = "ID")

dfB[ ,'AGE'] <- 0
for(i in 2:length(dfB[,1])){
  if(dfB[i,'ID'] == dfB[i-1, 'ID']){
    dfB[i,'AGE'] <- dfB[i-1, 'AGE'] + 1
  }
}

给予:

> head(dfB)
  ID P.ID P.AB LS AGE
1  A <NA>   NA  5   0
2  A <NA>   NA  5   1
3  A <NA>   NA  5   2
4  A <NA>   NA  5   3
5  A <NA>   NA  5   4
6  A <NA>   NA  5   5

然后我想做的就是让R在REP列中加一个“ 1”,以显示某人复制的年份。例如。当 A 为3时, B 出生于 A ,因此 A 3岁的那一行获得1我一直在尝试使用%in%来做到这一点,但是努力使它符合多个条件。一种解决方法是将IDage粘贴在一起(再加上一个随机字符串以确保在我的较大数据集中没有虚假重复),但是这似乎缺乏高雅感,并且不必要复杂。我想知道一个人可以/如何将%in%用于多个条件

# Add 1 where an individual reproduced
dfB[,'REP'] <- 0
dfB[,'T1'] <- paste0(dfB[,'AGE'],  "abcdefghijk656hjhjhj", dfB[,'ID'])
dfB[,'T2'] <- paste0(dfB[,'P.AB'], "abcdefghijk656hjhjhj", dfB[,'P.ID'])
dfB[,'REP'][dfB[,'T1'] %in% dfB[,'T2']] <- 1
dfB[,'T2'] <- dfB[,'T1'] <- NULL
dfB

输出将如下所示:

> dfB
   ID P.ID P.AB LS AGE REP
1   A <NA>   NA  5   0   0
2   A <NA>   NA  5   1   0
3   A <NA>   NA  5   2   0
4   A <NA>   NA  5   3   1
5   A <NA>   NA  5   4   1
6   A <NA>   NA  5   5   0
7   B    A    3  6   0   0
8   B    A    3  6   1   0
9   B    A    3  6   2   1
10  B    A    3  6   3   0
11  B    A    3  6   4   1
12  B    A    3  6   5   0
13  B    A    3  6   6   0
14  C    A    4  3   0   0
15  C    A    4  3   1   0
16  C    A    4  3   2   0
17  C    A    4  3   3   0
18  D    B    2  4   0   0
19  D    B    2  4   1   0
20  D    B    2  4   2   0
21  D    B    2  4   3   0
22  D    B    2  4   4   0
23  E    B    4  5   0   0
24  E    B    4  5   1   0
25  E    B    4  5   2   0
26  E    B    4  5   3   0
27  E    B    4  5   4   0
28  E    B    4  5   5   0

我尝试了这个(以及其中的一些变体),它很接近,可以将它们正确地添加到合适的个人,但是在错误的年份-看到 A B 都可以复制,并且复制发生在2、3和4岁(总共6个事件),但是 A B 都没有复制到4岁,而< em> A 也在3岁时复制, B 也在2岁时复制(总共4个事件):

dfB[,'REP'][dfB[,'P.ID'] %in% dfB[,'ID'] & dfB[,'P.AB'] %in% dfB[,'AGE']] <- 1  
dfB[,'REP'][dfB[,'ID'] %in% dfB[,'P.ID'] & dfB[,'AGE'] %in% dfB[,'P.AB'] ] <- 1

作为对此的扩展,我希望每个年龄段的后代数量而不是1或0,这是可行的(我更改了dfA,所以 B C 是双胞胎),但效率可能也很低:

# Counts of offspring per year
dfA[,'PASTED'] <- paste0(dfA[,'P.ID'], "randomtext",  dfA[,'P.AB'])
# Create rep column
dfB[,'REP'] <- 0
# Paste together ID and AGE columns to give unique row identifiers
dfB[,'T1'] <- paste0(dfB[,'AGE'],  "randomtext", dfB[,'ID'])
dfB[,'T2'] <- paste0(dfB[,'P.AB'], "randomtext", dfB[,'P.ID'])
# Add Reps
dfB[,'REP'][dfB[,'T1'] %in% dfB[,'T2']] <- table(dfA[,'PASTED'])
# Remove excess columns
dfB[,'T2'] <- dfB[,'T1'] <- NULL

1 个答案:

答案 0 :(得分:0)

如果您正在考虑将%in%用于多列,那么您可能正在寻找合并/联接。您可以使用基数R来完成所有操作,但是我发现使用dplyr

的帮助会更容易一些。
library(dplyr)
dfB %>% 
  select(P.ID, P.AB) %>% 
  distinct() %>% 
  filter(!is.na(P.ID)) %>% 
  rename(ID=P.ID, AGE=P.AB) %>% 
  mutate(REP=1) %>% 
  left_join(dfB, .) %>% 
  mutate(REP=coalesce(REP, 0))

基本上,您只是从数据中找到唯一的父/年龄值,然后将其重新连接到相同的data.frame,但在不同的列上匹配。