我正在尝试将一些旧的Excel函数翻译成R,识别昆虫爆发的最后一步对我来说是最具挑战性的。输入将包括两个时间序列数据集:一个二进制数据集报告多棵树的爆发或非爆发情况,以及一个等效的树轮宽度指数数据集,表示同一棵树和同一时间尺度的低生长或高生长。
我将首先张贴Excel代码和它试图做什么,然后R样本dfs下面:
=IF((( IF( outbreak.year > prev.outbreak.year; SMALL( index.year : INDIRECT( ADDRESS(( ROW( outbreak.year) + (( MATCH( 0; outbreak.year : 100th.outbreak.ahead; 0)) - 1) - 1); COLUMN( index.year))); 1))) < 1.28); 1; IF( outbreak.year; prev.outbreak.year; 0))
outbreak.year
、prev.outbreak.year
和outbreak.ahead
是指示是否发生爆发的二进制数据集;index.year
为树木年轮生长指数等大小的数据集。
此函数应首先确定爆发(1
)是否在非爆发(0
)年之后开始。如果是,则在某种while循环中使用SMALL()
、INDIRECT()
、ADDRESS()
、MATCH()
、ROW()
和COLUMN()
,以便在爆发数据集中向前查看,直到它停止报告1,然后查看索引数据集中等效"组"值中的最小数字,并查看它是否为< 1.28
。如果是,则将该组保留为1
s,如果不是,则将该组返回为非爆发条件或0
s。
。,我将使用这些作为输入:
df <- data.frame(t1 = c(0,0,0,1,1,1,1,1,0,0), t2 = c(0,0,0,0,0,1,1,1,1,1), t3 = c(0,0,1,1,1,1,1,1,1,0), t4 = c(0,0,1,1,1,1,1,0,0,1), t5 = c(0,1,1,1,1,1,0,0,1,1), row.names = 2000:2009)
df2 <- data.frame(t1 = c(0.12,0.54,-1.2,-0.3,-0.6,-1.29,-1.30,-0.5,0.3,0.5), t2 = c(0.9,0.8,0.32,0.9,-0.3,-0.4,-0.9,-1.1,-1.12,-1.14), t3 = c(-0.3,0.1,-1.11,-1.14,-1.45,-1.29,-1.68,-1.01,-0.6,0.1), t4 = c(-0.3,-0.34,-0.6,-0.9,-0.8,-1.1,-1.36,-0.4,0.5,0.3), t5 = c(1.45,-0.05,-0.12,-1.26,-0.21,-1.18,-1.01,-0.03,-0.6,-1.39), row.names = 2000:2009)
并且我希望df1看起来像df3,基于df2中是否有等效的[I,j]s小于-1.28。请注意,t2和t5列由于没有足够低的增长而丢失了报告的爆发,这在df2中可见:
df1 df2 df3
t1 t2 t3 t4 t5 t1 t2 t3 t4 t5 t1 t2 t3 t4 t5
2000 0 0 0 0 0 2000 0.12 0.90 -0.30 -0.30 1.45 2000 0 0 0 0 0
2001 0 0 0 0 1 2001 0.54 0.80 0.10 -0.34 -0.05 2001 0 0 0 0 0
2002 0 0 1 1 1 2002 -1.20 0.32 -1.11 -0.60 -0.12 2002 0 0 1 1 0
2003 1 0 1 1 1 2003 -0.30 0.90 -1.14 -0.90 -1.26 2003 1 0 1 1 0
2004 1 0 1 1 1 2004 -0.60 -0.30 -1.45 -0.80 -0.21 2004 1 0 1 1 0
2005 1 1 1 1 1 2005 -1.29 -0.40 -1.29 -1.10 -1.18 2005 1 0 1 1 0
2006 1 1 1 1 0 2006 -1.30 -0.90 -1.68 -1.36 -1.01 2006 1 0 1 1 0
2007 1 1 1 0 0 2007 -0.50 -1.10 -1.01 -0.40 -0.03 2007 1 0 1 0 0
2008 0 1 1 0 1 2008 0.03 -1.12 -0.60 0.50 -0.60 2008 0 0 1 0 1
2009 0 1 0 0 1 2009 0.50 -1.14 0.10 0.30 -1.39 2009 0 0 0 0 1
很难举例说明我的进步,因为我几乎不知道从哪里开始,或者我是否在正确的方向上工作。我目前开始尝试在df1中做一个while循环,并让它shift
+ 1延迟,直到它达到0,但然后我只是盯着整个(丑陋)的东西:
for( i in 1:dim( df1)[1]) {
for( j in 1:dim( df1)[2]) {
if( df1[i,j] > shift( df1, n = 1)) {
n <- 1
while( shift( df1, n = n) == 1) {
shift( df1, n =+ 1)
df3[i,j] <- 1
}
} else { df3[i,j] <- 0 }
}
}
谢谢你的帮助!
我会这样问你的问题。我有三个数据帧,A
, B
和C
。我需要使用B
的值将A
转换为C
。以下是数据帧:
A <- data.frame(c1=c(0, 1, 1, 0, 1, 1), c2=c(0, 1, 1, 1, 1, 0))
B <- data.frame(c1=c(2, 2, 4, 4, 2, 3), c2=c(0, 2, 3, 4, 1, 4))
C <- data.frame(c1=c(0, 1, 1, 0, 0, 0), c2=c(0, 1, 1, 1, 1, 0))
A
的每一列中连续的1
s的每一列代表一个组。如果B
中的相应值中没有大于3的值,我需要将A
中的序列转换为零。例如,A$c1
中的第一组对应于该列中的第二和第三个值。B
中的其中一个值大于3,所以我保留该组。A$c1
中的第二组对应于第5和第6个值,但这两个值都不大于3,所以我不保留该组中的值。
一个答案:
# Generate IDs for each sequence of 1s or 0s in each column of A
A.splits <- lapply(A, function(x) cumsum(c(0, abs(diff(x)))))
# Loop through each column, and split the values of B by the
# groups in A. If any group in any column contains values
# greater than 3, then return ones for that group else zero
A.keep <- Map(
ave, B, A.splits, MoreArgs=list(FUN=function(x) !!any(x > 3))
)
# remove ones by multiplying each column of `A` against `A.keep`
# and confirm results are the same as expected
all.equal(A * A.keep, C)
## TRUE