为什么这个条件查找不起作用?

时间:2015-06-09 18:53:12

标签: r data.table

编辑:修改反映下面的评论

我随时都有关于工人的一些数据。他们可能在任何一年中在不止一个职位上工作;我希望对数据进行子集化,以使至少一个位置的工作人员具有某些特征。

这是我的玩具数据:

set.seed(1643)
dt<-data.table(id=rep(1:1000,10),
               area=sample(letters,1e4,replace=T),
               position=sample(10,1e4,replace=T),
               firm_type=sample(5,1e4,replace=T),
               year=rep(2001:2010,each=1000),key="id")

我只希望工作人员area dowle位于position {{ 1}}。

不幸的是,7的编码方式从2005年开始改变了;在2005年之前,相关工人都在firm_type的公司。此后,可以接受firm_type==11类型。

我尝试了这个查找,但它不起作用:

2

具体来说,dt[.(dt[firm_type %in% ifelse(year<2005,1,1:2) &area %in% c("d","o","w","l","e") &position==7,unique(id)])] 运算符,如下面的注释中所述,不能逐行操作,因此我们得到(中间)输出,如:

%in%

@Frank启发了这种解决方法:

> dt[firm_type %in% ifelse(year<2005,1,1:2)
+    &area %in% c("d","o","w","l","e")
+    &position==7,table(firm_type,year)]
         year
firm_type 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010
        1    4    2    5    2    3    7    1    0    4    1
        2    2    4    4    6    4    5    9    8    1    2

我对此感到满意,但我很高兴看到是否有更好的解决此问题的方法,因为dt[.(dt[ifelse(year<2005,firm_type==1, firm_type %in% 1:2) &area %in% c("d","o","w","l","e") &position==7,unique(id)])] 未得到优化。

2 个答案:

答案 0 :(得分:1)

更快的方法。您可以推迟ifelse,直到您拥有更小的子集:

dt[ position==7L & area%in%c("d","o","w","l","e") & firm_type%in%1:2
][ifelse(year<2005,firm_type==1L,firm_type %in% 1:2),
  unique(id)
]

根据您的可读性,您也可以这样做:

dt[ position==7L & area%in%c("d","o","w","l","e") & firm_type%in%1:2
][!(year < 2005 & firm_type==2L),
  unique(id)
]

关于ifelse。 ifelse(cond,yes,no)速度很慢,因为它会计算yesno的所有内容,如果需要其中任何一个,请documented by @RicardoSaporta。在早期的OP迭代中提到的另一个想法 - (cond&yes)|((!cond)&no)也存在同样的问题。

冗长的方式。如果你的条件比较混乱,你可能想要明确说明:

my_areas     = c("d","o","w","l","e")
my_posns     = 7L
my_yearfirms = data.table(year=unique(dt$year))[,.(
  firm_type = if (year<2005) 1L else 1:2
),by=year]

merge(dt[position%in%my_posns & area%in%my_areas],my_yearfirms,by=c("year","firm_type"))[,
  unique(id)
]

最后一段代码可以是

  • 跳过(猜测上下文发生了什么)和
  • 在其他地方重复使用(如果你改变了条件)。

除非效率非常重要,否则我会这样做。

答案 1 :(得分:0)

除了“和”之外,只需使用“或”:

> dt[((firm_type == 1 ) | (firm_type ==2 & year>=2005))
+    &area %in% c("d","o","w","l","e")
+    &position==7,]