我正在尝试找到最好的(性能最好的)让表格的数据框在一年中的四个季节中获得一个名为“季节”的新栏目:
MON DAY YEAR
1 1 1 2010
2 1 1 2010
3 1 1 2010
4 1 1 2010
5 1 1 2010
6 1 1 2010
直接这样做是创建一个以MON和DAY列为条件的循环并逐个赋值,但我认为有更好的方法可以做到这一点。我在其他帖子中看到了ifelse
或:=
或apply
的建议,但所述的大多数问题只是二进制或者可以根据给定的单个函数f来分配值参数。
在我的情况下,我相信包含四个电台标签的矢量和某种条件就足够了,但我不知道如何把所有东西放在一起。我的情况类似于一个开关案例。
答案 0 :(得分:1)
如果行数很大,使用模运算以及算术运算符将逻辑值强制为0/1的事实会更有效:
d$SEASON <- with(d, c( "Winter","Spring", "Summer", "Autumn")[
1+(( (DAY>=21) + MON-1) %/% 3)%%4 ] )
第一个添加&#34; 1&#34;将括号内的所有结果的%% 4操作范围从0:3移到1:4。第二个减去&#34; 1&#34;将(内部)1:12范围移回0:11,(DAY >= 21)
将边界月份向前推进一个。
答案 1 :(得分:0)
我首先给出一个简单的答案,然后我将深入研究细节。 我快速做到这一点的方法是检查MON和DAY的值并输出正确的季节。这是微不足道的:
f=function(m,d){
if(m==12 && d>=21) i=3
else if(m>9 || (m==9 && d>=21)) i=2
else if(m>6 || (m==6 && d>=21)) i=1
else if(m>3 || (m==3 && d>=21)) i=0
else i=3
}
这个f
函数,给定一天和一个月,将返回一个对应于季节的整数(如果它是整数或字符串则不重要;整数只允许节省一点内存,但它具有技术性。
现在,您要将其应用于data.frame。不需要为此使用循环;我们将使用mapply
。 d
将是我们的模拟data.frame。我们将输出的因子设置得很好。
d=data.frame(MON=rep(1:12,each=30),DAY=rep(1:30,12),YEAR=2012))
d$SEA=factor(
mapply(f,d$MON,d$DAY),
levels=0:3,
labels=c("Spring","Summer","Autumn","Winter")
)
你有它!
我意识到季节永远不会改变21岁。如果需要微调,则应将三维数组定义为全局变量,以存储准确的天数。给定一个季节和一年,您可以访问相应的日期并使用正确的调用替换f
函数中的&#34; 21&#34;您显然会为该年添加第三个参数。
关于你在问题中提到的事情:
ifelse
是&#34; functionnal&#34;做一个条件测试的方法。在原子变量上,它只比条件语句略好,但它是矢量化的,这意味着如果参数是一个向量,它将在其元素上循环自身。我不熟悉它,但它是获得优化解决方案的方法mapply
源自&#34; sapply
家庭的apply
&#34;并允许在向量上调用具有多个参数的函数(请参阅?mapply
):=
是R中的标准运算符,这让我想到了下一点:data.table
!它是一个包,它提供了一个新的结构,可以扩展data.frame
以进行快速计算和输入(除其他外)。 :=
是该包中的运算符,允许定义新列。在我们的例子中,如果d[,SEA:=mapply(f,MON,DAY)]
是data.table,则可以写d
。如果您真的关心性能,我不能坚持使用data.table
,因为如果您有大量数据,这是一项重大改进。我不知道它是否会真正影响我使用我提出的解决方案计算时间。