我正在尝试编写一个函数,允许我在给定年份中找到多个事件的首次出现。事件发生在不同时刻的不同公司。因此,一个事件可能会在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
希望这澄清了之前的一些问题/评论
非常欢迎任何建议!
答案 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