在我的研究中,我经常遇到列表中的列表问题。今天,我再次运行一个程序,我不知道如何在R中最好地解决。我尝试用data.table
解决问题,但遇到了麻烦。
我有各种创业公司的数据,比如Startup1
,Startup2
等。对于每个创业公司,我都有关于投资者的信息,VC1
,VC2
等。我也有关于创业公司何时开始其活动的信息:StartYr
以及以投资者为特征的资金回合{{1资金回合发生的那一年VCNam
,以及收到的金额FRYr
。对于每个初创企业,融资轮次的数量都会发生变化,投资者的数量也会发生变化。
作为第一个练习,我尝试计算FMoney
和给定资助年度之间的时间。这是我的代码:
StartYr
这是我的输出:
library(data.table)
dtF1=data.table(VCNam=c("VC1","VC2"),FRYr=c("2006","2007"),FMoney=c(10000,20000))
dtF2=data.table(VCNam=c("VC1","VC3","VC4"),FRYr=c("2010","2011","2012"),FMoney=c(10,20,30))
dt=data.table(FirmName=c("Startup1","Startup2"),StartYr=c("2001","2005"),FdRounds=c(dtF1,dtF2))
dt[]
FNams=unique(dt$FirmName)
for (nam in FNams){
print(paste("dealing with firm",nam))
dtSub=dt[FirmName==nam,.(StartYr,FdRounds)]
StartYr=as.integer(dtSub[,StartYr])
print(StartYr)
print(dtSub[,FdRounds][[1]])
print(dtSub[,FdRounds][[2]])
FRYr=dtSub[,FdRounds][[3]]
print(as.integer(FRYr)-StartYr)
}
对于> dt[]
FirmName StartYr FdRounds
1: Startup1 2001 VC1,VC2
2: Startup2 2005 2006,2007
3: Startup1 2001 10000,20000
4: Startup2 2005 VC1,VC3,VC4
5: Startup1 2001 2010,2011,2012
6: Startup2 2005 10,20,30
and:
[1] "dealing with firm Startup1"
[1] 2001 2001 2001
[1] "VC1" "VC2"
[1] 10000 20000
[1] 9 10 11 # the right answer
[1] "dealing with firm Startup2"
[1] 2005 2005 2005
[1] "2006" "2007"
[1] "VC1" "VC3" "VC4"
[1] -1995 -1985 -1975 # a crazy answer.
,结果9 10 11对于Startup1
是正确的,而对于-1995等是正确的。检查显示,dt不再包含正确的元素顺序:VC名称,资金年度,资金。
问题1:我愿意使用list,dplyr或data.table这是此问题的建议方法。数据是数百家公司所以时间问题。
问题2:如何解决这个问题,这个问题代表了我一直遇到的问题?相关:有没有更多功能性的编程方式来处理这个问题?
答案 0 :(得分:4)
由于底层数据结构的复杂设计,很难分析for
循环返回错误答案的原因。另一个问题是FRYr
和StartYr
作为字符给出,但OP想要计算这些差异。
因此,我建议使用一个“干净”的设计,只有两个data.table
以类似SQL的方式:
FdRounds
,Startup
使用FirmName
作为关键字来识别两个表中彼此相关的行。
这些可以从现有数据构建:
library(data.table)
dtF1 = data.table(
FirmName = "Startup1",
VCNam = c("VC1", "VC2"),
FRYr = c("2006", "2007"),
FMoney = c(10000, 20000)
)
dtF2 = data.table(
FirmName = "Startup2",
VCNam = c("VC1", "VC3", "VC4"),
FRYr = c("2010", "2011", "2012"),
FMoney = c(10, 20, 30)
)
FdRounds <- rbindlist(list(dtF1, dtF2))
FdRounds[, FRYr := as.integer(FRYr)]
FdRounds
FirmName VCNam FRYr FMoney 1: Startup1 VC1 2006 10000 2: Startup1 VC2 2007 20000 3: Startup2 VC1 2010 10 4: Startup2 VC3 2011 20 5: Startup2 VC4 2012 30
Startups = data.table(
FirmName = c("Startup1", "Startup2"),
StartYr = c("2001", "2005")
)
Startups[, StartYr := as.integer(StartYr)]
现在,我们可以加入两个表并进行计算
FdRounds[Startups, on = "FirmName"][, FdYearAfterStart := FRYr - StartYr][]
FirmName VCNam FRYr FMoney StartYr FdYearAfterStart 1: Startup1 VC1 2006 10000 2001 5 2: Startup1 VC2 2007 20000 2001 6 3: Startup2 VC1 2010 10 2005 5 4: Startup2 VC3 2011 20 2005 6 5: Startup2 VC4 2012 30 2005 7
对于更紧凑的视图,数据可由启动公司聚合:
FdRounds[Startups, on = "FirmName"][, FdYearAfterStart := FRYr - StartYr][
, lapply(.SD, toString), by = .(FirmName, StartYr)]
FirmName StartYr VCNam FRYr FMoney FdYearAfterStart 1: Startup1 2001 VC1, VC2 2006, 2007 10000, 20000 5, 6 2: Startup2 2005 VC1, VC3, VC4 2010, 2011, 2012 10, 20, 30 5, 6, 7
从加入的结果可以很容易地计算出每个创业公司在所有投资者中获得的总资金:
FdRounds[Startups, on = "FirmName"][
, .(TotalFunding = sum(FMoney)), by = .(FirmName, StartYr)][]
FirmName StartYr TotalFunding 1: Startup1 2001 30000 2: Startup2 2005 60
这种方法也更加通用,因为它也允许投资者汇总:
FdRounds[Startups, on = "FirmName"][
, .(NumberFR = .N, TotalFunding = sum(FMoney),
InYears = paste(range(FRYr), collapse = "-")), by = VCNam]
VCNam NumberFR TotalFunding InYears 1: VC1 2 10010 2006-2010 2: VC2 1 20000 2007-2007 3: VC3 1 20 2011-2011 4: VC4 1 30 2012-2012
FdRounds[Startups, on = "FirmName"][
, .(NumberFR = .N, TotalFunding = sum(FMoney),
InvestedIn = toString(FirmName)), by = VCNam]
VCNam NumberFR TotalFunding InvestedIn 1: VC1 2 10010 Startup1, Startup2 2: VC2 1 20000 Startup1 3: VC3 1 20 Startup2 4: VC4 1 30 Startup2