ste*_*eve 2 r data-manipulation
所有,
我工作的公司给了我这些数据.简而言之,它是TSCS数据,公司作为横截面单位,时间单位为财政年度.每家公司都有各种账户.我有兴趣为特定公司创建每个帐户的总支出.
我可以提供下面数据的简单说明.让我们firm感兴趣的截单元.每个firm都有公司花钱的各种账户.有些账户对所有公司都很常见,有些则是独一无二的.并非每个人firm都有在一年中花在账户上的钱.事实上,有些人直到数据之后才有资格获得账户,而其他人则退出(因此,面板数据可能被认为是不平衡的).因此,我提供的数据中的NA可以被视为0,尽管它有点问题.有些公司在某一年有资格但没有在账户中收款.由于辍学或迟到,其他公司不合格.
数据看起来像这样,它是以宽格式提供给我的.这是一个简化版本的插图.在此图示中,firm=B在1990 firm=C财政年度没有资格获得帐户,并在1992财年退出.
firm account FY1990 FY1991 FY1992
A Account 1 500 900 1000
A Account 2 30 40 40
A Account 3 NA 60 20
A Account 4 NA 35 NA
B Account 1 NA 340 60
B Account 2 NA 500 800
B Account 3 NA 800 NA
B Account 4 NA 60 1000
C Account 1 1000 400 NA
C Account 5 500 60 NA
C Account 8 60 1000 NA
D Account 1 400 400 400
D Account 2 NA 1000 1000
D Account 3 300 40 300
D Account 6 NA 300 300
D Account 7 900 900 1000
D Account 8 1000 1200 1500
Run Code Online (Sandbox Code Playgroud)
我想做的(并被告知要做)是修改这些数据,使它看起来像这样:
firm account FY1990 FY1991 FY1992
A Account 1 500 900 1000
A Account 2 30 40 40
A Account 3 NA 60 20
A Account 4 NA 35 NA
A TOTAL 530 1035 1060
B Account 1 NA 340 60
B Account 2 NA 500 800
B Account 3 NA 800 NA
B Account 4 NA 60 1000
B TOTAL NA 1700 1860
C Account 1 1000 400 NA
C Account 5 500 60 NA
C Account 8 60 1000 NA
C TOTAL 1560 1460 NA
D Account 1 400 400 400
D Account 2 NA 1000 1000
D Account 3 300 40 300
D Account 6 NA 300 300
D Account 7 900 900 1000
D Account 8 1000 1200 1500
D TOTAL 2600 3840 4500
Run Code Online (Sandbox Code Playgroud)
我可以在Excel或其他电子表格程序中轻松地执行此操作,但这将是乏味的,并且它会比我使用R对此进行编程时引发更多人为错误.我并不反对使用总计创建新数据框,而不是尝试在给定公司的所有帐户下添加一行.如果给定公司的总额不符合某一财政年度的账户,则可能更容易设置0.我总是可以将一些零重新编码为NAs,并自动执行该过程.
我的假设是这需要一个循环,但我是R编程的新手.任何投入将不胜感激.
下图中可重复使用的代码如下图所示.
firm <- c("A","A","A","A","B","B","B","B","C","C","C","D","D","D","D","D","D")
account <- c("Account 1","Account 2","Account 3","Account 4","Account 1","Account 2","Account 3","Account 4","Account 1","Account 5","Account 8","Account 1","Account 2","Account 3","Account 6","Account 7","Account 8")
FY1990 <- c(500,30,NA,NA,NA,NA,NA,NA,1000,500,60,400,NA,300,NA,900,1000)
FY1991 <- c(900,40,60,35,340,500,800,60,400,60,1000,400,1000,40,300,900,1200)
FY1992 <- c(1000,40,20,NA,60,800,NA,1000,NA,NA,NA,400,1000,300,300,1000,1500)
Data=data.frame(firm=firm, account=account, FY1990=FY1990, FY1991=FY1991, FY1992=FY1992)
summary(Data)
Data
Run Code Online (Sandbox Code Playgroud)
这是一种data.table方法:
library(data.table)
dt <- data.table(Data)
dt[, rbind(.SD,
c("TOTAL",
lapply(.SD[, grepl("^FY[0-9]+", names(.SD)), with = F],
function(x){sum(x, na.rm = !all(is.na(x)))}
)),
use.names = F),
by = firm]
Run Code Online (Sandbox Code Playgroud)
这样做如下:我们遍历by = firmfirm (),对于每个公司我们堆栈(rbind)......
.SD) "TOTAL",其余由长lapply调用创建.该lapply只与一个公司在一个时间相关的数据进行操作.该数据存储在.SD上面提到的特殊临时data.table 中.列名也可以直接命名(但不在此示例中).
该lapply电话的工作原理如下:我们遍历向量的列表(通过选择使用将我们的名字列中选择grepl正则表达式测试),并为每个向量我们应用的特殊变体sum的功能.
sum函数的这个变体查看完整的向量x,其中 - 从我们迭代的列表中选择此向量,并且一次只有一个公司关联的行 - 并检查是否存在任何非NA条目x(即,如果!all(is.na(x))).如果存在,则将这些条目相加,将任何NAs视为零(自na.rm=TRUE); 如果没有,它返回NA(因为na.rm=FALSE我们有NAs).
有关na.rm参数的详细信息,请查看?sum.类似地,通过使用或搜索可以找到有关上述函数(grepl,lapply...)的详细信息.?term?"term"
by=firm然后,该选项将公司的结果堆叠起来,并将"公司"作为第一列.
这是结果:
firm account FY1990 FY1991 FY1992
1: A Account 1 500 900 1000
2: A Account 2 30 40 40
3: A Account 3 NA 60 20
4: A Account 4 NA 35 NA
5: A TOTAL 530 1035 1060
6: B Account 1 NA 340 60
7: B Account 2 NA 500 800
8: B Account 3 NA 800 NA
9: B Account 4 NA 60 1000
10: B TOTAL NA 1700 1860
11: C Account 1 1000 400 NA
12: C Account 5 500 60 NA
13: C Account 8 60 1000 NA
14: C TOTAL 1560 1460 NA
15: D Account 1 400 400 400
16: D Account 2 NA 1000 1000
17: D Account 3 300 40 300
18: D Account 6 NA 300 300
19: D Account 7 900 900 1000
20: D Account 8 1000 1200 1500
21: D TOTAL 2600 3840 4500
firm account FY1990 FY1991 FY1992
Run Code Online (Sandbox Code Playgroud)
您必须先安装并加载data.table包.