R:搜索&在时间序列中隔离多个第一次出现

时间:2014-03-11 11:09:15

标签: r search matrix time-series

我正在尝试编写一个函数,允许我在给定年份中找到多个事件的首次出现。事件发生在不同时刻的不同公司。因此,一个事件可能会在1980年第一次发生,然后在1981年确定为b。在这种情况下,我需要找到的是c_1980和矩阵中的相关值。

但是,如果事件没有发生,直到1986年确实发生了事情并且在1986年确定了事件,那么我需要找到a_1986和e_1986的结果,它们各自的值在矩阵中。

我的(2500 * 800)矩阵在垂直轴上有2500个不同的事件,在水平轴上有800个不同的year_firm组合。所有值都在0到10之间(在实际矩阵中,在0到2之间的示例中),绝大多数都是零。

示例数据:

av<-matrix(rep(0:2),10,40)
av[1:7,]=0 ; av[9,3:14]=0
av[,c(22,38)]=1
colnames(av)<-paste(c("a","b","c","d","e"),rep(1980:1987, each=5),sep="_")
col.av<-colnames(av)
rownames(av)<-paste("X",1:10,sep="")
row.av<-rownames(av)

我使用的主要公式给出了第一次出现的矩阵中的位置:

first<-max.col(av>0,"first") 

这可以很好地找到第一次出现。然而,正如数据显示的那样,有时这是同一年中的多次出现(例如,第8行中的事件发生在1980年,对于公司a,b,d和e - >,因为这是第8行成为第8年非零我需要找到4个不同的值作为输出)。

到目前为止,我的代码基本上是一个补丁解决方案

avdum1<-matrix(cbind(seq(1:nrow(av)),first),nrow=nrow(av),ncol=2)
avdum2<-matrix(cbind(row.av,first),nrow=nrow(av),ncol=2)

使用avdum1和avdum2以及原始的行和列名称然后我可以设计一个矩阵,它给出了原始矩阵中的第一个出现,以及第一次出现的精确值(1或2)以及公司年度组合

firsttime<-matrix(cbind(row.av,col.av[first],av[avdum1]),nrow=nrow(av),ncol=3)

到目前为止一切顺利。 现在,为了在同一年找到其他第一次出现,我所做的是

av[avdum1]<-0

这将原始的第一次出现置于零,然后我再次遍历整个过程,然后展开firsttime矩阵,将列名称拆分为年,公司名称为a,b,c,d,e,比较年,看看第二次出现是否在同一年发生。如果确实如此,我必须第三次重新运行整个过程,依此类推(我的真实数据集有40家公司)。

这变得相当麻烦,所以我想知道是否有更聪明的方法吗?根据事件在矩阵中的相对位置,一旦发现了积极事件,可能会进行本地化搜索吗?

最终的预期结果:

(如果复制示例数据,则可以在生成矩阵时忽略初始警告)

对于行1到7,结果将是b_1984,值为1 对于第8行,结果应为a_1980,1,b_1980为2,d_1980为1,e_1980为2 对于第9行,a_1980为2 对于第10行,b_1980为1,c_1980为2,e_1980为1

希望这澄清了之前的一些问题/评论

非常欢迎任何建议!

1 个答案:

答案 0 :(得分:1)

我试了一下,虽然我的路径与你的路径不同。也许,可能有一种方法来操纵你的数据,以给出结果(也许,甚至,快速),但我更喜欢使用&#34; long&#34;格式而不是。长格式也可以使用&#34; data.table&#34;等软件包快速操作。和&#34; dplyr&#34;。

首先,我将您的av转换为以下格式的长格式:

#turn to long format
long_DF = as.data.frame(as.table(av), responseName = "value")

#tidy up
tmp = do.call(rbind.data.frame, strsplit(as.character(long_DF[[2]]), "_"))
long_DF$firm = tmp[, 1] ; long_DF$year = tmp[, 2] 
long_DF$event = long_DF[[1]] ; long_DF = long_DF[-(1:2)]

long_DF[c(1,4,5,8,15,16,20), ]
#   value firm year event
#1      0    a 1980    X1
#4      0    a 1980    X4
#5      0    a 1980    X5
#8      1    a 1980    X8
#15     0    b 1980    X5
#16     0    b 1980    X6
#20     1    b 1980   X10

从现在开始,我想会有许多不同的,更有效的方法,但我只能想出以下内容:

#3D array
res = xtabs(value ~ firm + year + event, long_DF)

res[, , 3, drop = F]
#, , event = X3
#
#    year
#firm 1980 1981 1982 1983 1984 1985 1986 1987
#   a    0    0    0    0    0    0    0    0
#   b    0    0    0    0    1    0    0    0
#   c    0    0    0    0    0    0    0    1
#   d    0    0    0    0    0    0    0    0
#   e    0    0    0    0    0    0    0    0

对于每个第三维,您可以搜索1)哪些值([行,列])高于0和2)哪些值在可用的最小列中(即,事件发生在较早的年份)。这个的实现可以是以下功能:

#function to apply to each 3rd dimension
f1 = function(x) {
      wh = which(x > 0, arr.ind = T)
      wh2 = which(wh[, "col"] == min(wh[, "col"]))
      wh3 = wh[wh2, , drop = F]
      cbind.data.frame(firm = rownames(x)[wh3[, 1]],
                       year = colnames(x)[wh3[, 2]], 
                       val = x[wh3])
} 

将功能应用于每个第三维;即对每个事件:

ret = apply(res, 3, f1)
#ret
ans = cbind.data.frame(event = rep(names(ret), lapply(ret, nrow)), 
                       do.call(rbind.data.frame, apply(res, 3, f1)))
ans
#      event firm year val
#X1       X1    b 1984   1
#X2       X2    b 1984   1
#X3       X3    b 1984   1
#X4       X4    b 1984   1
#X5       X5    b 1984   1
#X6       X6    b 1984   1
#X7       X7    b 1984   1
#X8.1     X8    a 1980   1
#X8.2     X8    b 1980   2
#X8.3     X8    d 1980   1
#X8.4     X8    e 1980   2
#X9       X9    a 1980   2
#X10.1   X10    b 1980   1
#X10.2   X10    c 1980   2
#X10.3   X10    e 1980   1