R:涉及多个数据帧的ifelse语句测试

时间:2016-10-05 20:36:17

标签: r if-statement dataframe dplyr

我正在尝试使用ifelse创建一个新变量,将两个data.frames的数据组合在一起(类似于this问题,但没有因素)。

我的问题是,df1以年度数据为特色,而df2中的变量在时间上汇总:例如df1有多个obs(1997,1998,...,2005),df2只有一个范围(1900-2001)。

为了说明,2x2示例看起来像

df1$id <- c("2","20")
df1$year <- c("1960","1870")

df2$id <- df1$id
df2$styear <- c("1800","1900")
df2$endyear <- c("2001","1950")

我希望以这样的方式组合两者,以便匹配id(同时存在两个变量),此外,df1中的年份在df2的范围内。我尝试了以下

df1$new.var <- ifelse(df1$id==df2$id & df1$year>=df2$styear & 
df1$year<df2$endyear,1,0)

理想情况下应分别返回1和0。

但我收到了警告信息:

  

1:在df1 $ id == df2 $ id中:较长的对象长度不是倍数   较短的物体长度

     

2:在df1 $ year&gt; = df2 $ styear:较长的对象长度不是a   多个较短的物体长度

     

3:在df1 $ year&lt; df2 $ endyear:较长的对象长度不是a   多个较短的物体长度

对于记录,'真实'df1有500个障碍,df2有14.我怎样才能使这个工作?

编辑:我意识到df2中的某些障碍被重复,有多个句号,例如

id    styear    endyear
1      1800      1915
1      1950      2002
2      1912      1988
3      1817      2000

所以,我相信我需要的东西就像双重ifelse:

df1$new.var <- ifelse(df1$id==df2$id & df1$year>=df2$styear & 
df1$year<df2$endyear | df1$year>=df2$styear & 
df1$year<df2$endyear,1,0)

显然,这不起作用,但它是摆脱重复问题的一种方法。

例如,如果id=1df1$year=1801,它将通过第一年范围测试(1801年是1800-1915之间),但是第二年测试失败(1801不是1950年至2002年之间) ),所以它只编码一次,没有添加额外的行(目前重复项添加额外的行)。

4 个答案:

答案 0 :(得分:1)

df1$id <- c("2","20")
df1$year <- c("1960","1870")

df2$id <- df1$id
df2$styear <- c("1800","1900")
df2$endyear <- c("2001","1950")

library(dplyr)
df3 <- left_join(df1,df2,by = "id") %>% filter(year <= endyear,year >= startyear)

我强烈建议使用dplyr软件包进行数据操作。

答案 1 :(得分:0)

以基地R:

df1 <- data.frame(id=c(2,20,22), year=c(1960,1870, 2016))
df2 <- data.frame(id=c(2,20,21), styear=c(1800,1900,2000), endyear=c(2001,1950,2016))

df1
id year
1  2 1960
2 20 1870
3 22 2016

df2

id styear endyear
1  2   1800    2001
2 20   1900    1950
3 21   2000    2016

df1 <- merge(df1, df2, by='id', all.x = TRUE)
df1$new.var <- !is.na(df1$styear) & df1$year>=df1$styear & df1$year< df1$endyear
df1 <- df1[c('id', 'year', 'new.var')]

df1
  id year new.var
1  2 1960    TRUE
2 20 1870   FALSE
3 22 2016   FALSE

答案 2 :(得分:0)

好吧,我让它适合自己。要注意,它很复杂,可能包含一些冗余。在简要了解数据争用cheatsheet之后,假设您df1df2具有相同的vardf2包含new.var,可以做到以下几点:

library(dplyr)
#Join everything, all values and rows
df3 <- full_join(df1,df2,by="id")
#filter out obs those year is greater than endyear
df3 <- filter(df3,df3$year<=df3$endyear)
#same, the other way around
df3 <- filter(df3,df3$year>=df3$styear) 
df3 <- distinct(df3) #remove duplicate rows (at least I had some)

据我所知,通过查看最终结果,此方法仅从正确的时间段中提取信息,同时将所有其他时间段放在df2中。然后,这是与原始data.frame(df1)合并并填写NA的问题:

df1 <- merge(df1,df3,by=(id),all.x=TRUE)
df1 <- distinct(df1) #just to make sure, I still had three
df1$new.var <- ifelse(is.na(df1$new.var),0,df1$new.var)

这就是我想要的。

答案 3 :(得分:0)

使用library(data.table) setDT(df1); setDT(df2) # converting to data.table in place df1[, new.var := df2[df1, on = .(id, styear <= year, endyear >= year), .N > 0, by = .EACHI]$V1] df1 # id year new.var #1: 2 1960 TRUE #2: 20 1870 FALSE devel version(1.9.7 +)中的非等联接可以轻松有效地解决这个问题:

df2

以上联接在df1by = .EACHI.N)的每一行中查找filterList (filterText) { var updatedList = this.props.array; return updatedList.filter(function(item){ var split = item.name.split(" "); console.log(split, filterText); return split === filterText; }); } 中的匹配项,并检查匹配行数({{1}})。