我认为我仍然不清楚R在矢量化语句中如何处理单个元素。
我有以下代码
df1$flag <- ifelse(df1$year < 2013 &
df1$year == df2$year &
as.character(df1$code) == as.character(df2$code), 'Y', df1$flag)
我正在对此数据进行操作
year <- c(2011, 2012, 2011, 2013, 2014, 2016, 2016, 2015, 2016, 2010)
flag <- 'N'
code <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
df1 <- data.frame(year, flag, code)
rm(year)
rm(flag)
rm(code)
year <- c(2015, 2013, 2011, 2012, 2016, 2016, 2010)
code <- c(5, 7, 3, 2, 14, 99, 10)
df2 <- data.frame(year, code)
df1$flag <- ifelse(df1$year < 2013 &
df1$year == df2$year &
as.character(df1$code) == as.character(df2$code), 'Y', df1$flag)
我希望这是输出
> df1
year flag code
1 2011 1 1
2 2012 Y 2
3 2011 Y 3
4 2013 1 4
5 2014 1 5
6 2016 1 6
7 2016 1 7
8 2015 1 8
9 2016 1 9
10 2010 Y 10
但相反,我得到了这个
> df1
year flag code
1 2011 1 1
2 2012 1 2
3 2011 Y 3
4 2013 1 4
5 2014 1 5
6 2016 1 6
7 2016 1 7
8 2015 1 8
9 2016 1 9
10 2010 1 10
我希望ifelse
语句将df1$year
和df1$code
的每个元素与df2$year
和df2$code
的每个元素进行比较,但它并不是==
。看起来像%in%
或for(i in 1:nrow(df1)) {
for(z in 1:nrow(df2)) {
if(df1$year[i] < 2013 & df1$year[i] == df2$year[z] &
as.character(df1$code[i]) == as.character(df2$code[z]))
df1$flag[i] <- 'Y'
}
}
会这样做。
换句话说,我想要的是比较像这样的元素
for
显然像这样使用==
会大大减慢执行速度并且无法使用,但它看起来不像%in%
,identical()
,all.equal()
或{{ 1}}也将执行我在for
循环中描述的内容。如何获得我在R?
答案 0 :(得分:1)
ifelse
逐个元素地比较两个向量(假设它们具有相同的长度,如果没有,则小向量将被循环使用它们)。
这意味着你的代码:
df1$flag <- ifelse(df1$year < 2013 &
df1$year == df2$year &
as.character(df1$code) == as.character(df2$code), 'Y', df1$flag)
相当于:
for(i in 1:nrow(df1)) {
if(df1$year[i] < 2013 & df1$year[i] == df2$year[i] &
as.character(df1$code[i]) == as.character(df2$code[i]))
df1$flag[i] <- 'Y'
}
假设df1和df2具有相同的行数。
更新
这是merge
而不是for loop
或if else
的情况。基本上,您希望合并年份和代码上的数据集,然后如果年份小于2013年,则指定'Y'
标记。
所以,我在df2中添加了一个标识符,如下所示:
year <- c(2015, 2013, 2011, 2012, 2016, 2016, 2010)
code <- c(5, 7, 3, 2, 14, 99, 10)
flag2 <- 'Y'
#make sure the flags are not factors
df2 <- data.frame(year, code, flag2, stringsAsFactors = FALSE)
然后你就这样做了:
#merge on year and code
newdf <- merge(df1, df2, by = c('year', 'code'), all.x = TRUE)
#assign Y to flag if year < 2013 and flag2 == Y
newdf$flag[newdf$year < 2013 & newdf$flag2 == 'Y'] <- 'Y'
#delete flag2
newdf$flag2 <- NULL
newdf
停止
year code flag
1 2010 10 Y
2 2011 1 N
3 2011 3 Y
4 2012 2 Y
5 2013 4 N
6 2014 5 N
7 2015 8 N
8 2016 6 N
9 2016 7 N
10 2016 9 N