使用data.tables

时间:2018-04-14 08:17:24

标签: r dplyr data.table

在我的研究中,我经常遇到列表中的列表问题。今天,我再次运行一个程序,我不知道如何在R中最好地解决。我尝试用data.table解决问题,但遇到了麻烦。

我有各种创业公司的数据,比如Startup1Startup2等。对于每个创业公司,我都有关于投资者的信息,VC1VC2等。我也有关于创业公司何时开始其活动的信息: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:如何解决这个问题,这个问题代表了我一直遇到的问题?相关:有没有更多功能性的编程方式来处理这个问题?

1 个答案:

答案 0 :(得分:4)

由于底层数据结构的复杂设计,很难分析for循环返回错误答案的原因。另一个问题是FRYrStartYr作为字符给出,但OP想要计算这些差异。

因此,我建议使用一个“干净”的设计,只有两个data.table以类似SQL的方式:

  1. 所有资金轮次FdRounds
  2. 和所有创业公司的基础数据的第二个Startup
  3. 使用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