【问题标题】:Matching (and summing) many fields to one in R在 R 中将许多字段匹配(和求和)为一个
【发布时间】:2013-03-16 17:40:33
【问题描述】:

我有一个数据文件 (.csv),其中每个观测值都是 333 个区之一。每个区都有一个 ID,例如 1101、1102、...。其次,我有另一个数据文件 (.csv),其中每个观察值都是 112,975 个城镇之一,包括人口数据。城镇数据有一个 District_ID 字段。每个区大约有300个镇。所以,district_ID == 1101 有 1 个区,district_ID == 1101 有大约 300 个镇。

我想在我的区数据集中创建区级人口变量。这意味着将多个城镇观测值与每个单一地区观测值相匹配,并对城镇级人口求和。

谢谢!

【问题讨论】:

    标签: r


    【解决方案1】:

    data.table 解决方案:

    #some example data
    set.seed(42)
    districts <- data.frame(district_ID=1:10,whatever=rnorm(10))
    towns <- data.frame(town=1:100,district_ID=rep(1:10,each=10),
                        population=rpois(100,sample(c(1e3,1e4,1e5))))
    
    library(data.table)
    districts <- data.table(districts,key="district_ID")
    towns <- data.table(towns,key="district_ID")
    
    #calculate district population
    temp <- towns[,list(district_pop=sum(population)),by=district_ID]
    #merge result with districts data.table
    districts <- merge(districts,temp)
    
    #    district_ID    whatever district_pop
    # 1:           1  1.37095845       434886
    # 2:           2 -0.56469817       334084
    # 3:           3  0.36312841       342241
    # 4:           4  0.63286260       433224
    # 5:           5  0.40426832       334039
    # 6:           6 -0.10612452       342810
    # 7:           7  1.51152200       433362
    # 8:           8 -0.09465904       333810
    # 9:           9  2.01842371       342035
    # 10:          10 -0.06271410       432302
    

    【讨论】:

    • 我怎样才能概括这一点来总结towns 中的所有列,而不仅仅是一个(以上,人口),由district_ID 索引?
    • temp &lt;- towns[,lapply(.SD, sum),by=district_ID] 也可能使用.SDcols。阅读文档。
    【解决方案2】:

    编辑:更大数据集的基准测试。

    使用tapply函数计算每个区的人口:

    districtdata$population<-
      tapply(towndata$population,towndata$district_ID,sum)[districts$district_ID]
    

    一些基准测试,只是为了好玩:

    fn1<-function(districts,towns) 
    {
      districts$population<-
           tapply(towns$population,towns$district_ID,sum)[districts$district_ID]
    
      districts
    }
    fn2<-function(districts,towns) #Roland's data.table approach:
    { 
      districts <- data.table(districts,key="district_ID")
      towns <- data.table(towns,key="district_ID")
      temp<-towns[,list(district_pop=sum(population)),by=district_ID]
      merge(districts,temp)
    }
    
    
    
    set.seed(42)
    districts <- data.frame(district_ID=1:300,whatever=rnorm(300))
    towns <- data.frame(town=1:100000,district_ID=rep(1:300,each=300),
                        population=rpois(300000,sample(c(1e3,1e4,1e5))))
    
    microbenchmark(fn1(districts,towns),fn2(districts,towns))
    Unit: milliseconds
                      expr       min        lq    median        uq       max neval
     fn1(districts, towns) 215.29266 231.47103 243.72353 265.28280 355.43895   100
     fn2(districts, towns)  20.03636  27.51046  36.11116  58.56448  88.70766   100
    

    【讨论】:

    • @Roland 是的,我同意,改变了基准。我有点惊讶tapply 这么慢。
    【解决方案3】:

    怎么样:

    aggregate(population ~ district_ID, towns, sum)
    

    (基于罗兰的综合数据)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-28
      • 1970-01-01
      • 1970-01-01
      • 2018-08-14
      • 2021-08-07
      相关资源
      最近更新 更多