【问题标题】:R: multiply columns by rows to create country-specific indexR:将列乘以行以创建特定于国家/地区的索引
【发布时间】:2013-06-24 09:50:17
【问题描述】:

我正在尝试根据某些食品商品的进口份额创建一个特定于国家/地区的指数。

我有以下数据:价格包含一些食品商品价格的时间序列数据。 Weights 包含有关商品的特定国家/地区进口份额的数据(请参阅模拟数据)。

我想做的是创建一个特定国家的食品价格指数,该指数是进口商品价格系列乘以进口份额的总和。

因此,在示例数据中,澳大利亚的食品价格指数为:

FOODct = 0.12 * WHEATt + 0.08 * SUGARt

其中c 表示国家和t 时间。

所以基本上我的问题是:如何将每个国家/地区的列乘以行?

我对 R 有一些经验,但试图解决这个问题我似乎已经超出了我的体重。我也没有在其他地方找到任何有用的指针,所以我希望你们中的任何人都可能有好的建议。

## Code to create mock data:

## Generate data on country weights
country<-c(rep("Australia",2),rep("Zimbabwe",3))
item<-c("Wheat","Sugar","Wheat","Sugar","Soybeans")
itemcode<-c(1,2,1,2,3)
share<-c(0.12,0.08,0.16,0.08,0.03)
weights<-data.frame(country,item,itemcode,share)

## Generate data on price index
date<-seq(as.Date("2005/1/1"),by="month",length.out=12)
Wheat<-runif(12,80,160)
Sugar<-runif(12,110,230)
Soybeans<-runif(12,60,130)
prices<-data.frame(date,Wheat,Sugar,Soybeans)

编辑:解决方案

感谢 alexwhan 的建议(不幸的是,由于缺乏 stackoverflow 街头信誉,我无法投票)。 dnlbrky 是最容易用原始数据实现的解决方案。

## Load data.table package
require(data.table)

## Convert data to data table
prices<-data.table(prices)
weights<-data.table(weights,key="item")

## Extract names for all the food commodities
vars<-names(prices)[!names(prices) %in% "date"] 

## Unstack items to create table in long format
prices<-data.table(date=prices[,date], stack(prices,vars),key="ind")

## Rename the columns
setnames(prices,c("values","ind"),c("price","item"))

## Calculate the food price index
priceindex<-weights[prices,allow.cartesian=T][,list(index=sum(share*price)),
                              by=list(country,date)]

## Order food price index if not done automatically
priceindex<-priceindex[order(priceindex$country,priceindex$date),]

【问题讨论】:

    标签: r dataframe multiplication


    【解决方案1】:

    这是一种选择。绝对会有一种更简洁的方法来做到这一点,但它应该能让你继续前进。

    首先,我要将weights 转换为宽格式,以便我们更轻松地使用它:

    library(reshape2)
    weights.c <- dcast(weights, country~item)
    #     country Soybeans Sugar Wheat
    # 1 Australia       NA  0.08  0.12
    # 2  Zimbabwe     0.03  0.08  0.16
    

    然后我使用apply 遍历weights.c 的每一行并计算“食品价格指数”(如果计算不正确,请告诉我,我想我按照这个例子是对的......) .

    FOOD <- as.data.frame(apply(weights.c, 1, function(x) 
      as.numeric(x[3]) * prices$Soybeans + 
      as.numeric(x[3])*prices$Sugar + as.numeric(x[4])*prices$Wheat))
    

    添加国家和日期标识符:

    colnames(FOOD) <- weights.c$country
    FOOD$date <- prices$date
    FOOD
    #    Australia Zimbabwe       date
    # 1   35.04337 39.99131 2005-01-01
    # 2   38.95579 44.72377 2005-02-01
    # 3   33.45708 38.50418 2005-03-01
    # 4   30.42181 34.04647 2005-04-01
    # 5   36.03443 39.90905 2005-05-01
    # 6   46.21269 52.29347 2005-06-01
    # 7   41.88694 48.15334 2005-07-01
    # 8   34.47848 39.83654 2005-08-01
    # 9   36.32498 40.60091 2005-09-01
    # 10  33.74768 37.17185 2005-10-01
    # 11  38.84855 44.87495 2005-11-01
    # 12  36.45119 40.11678 2005-12-01
    

    希望这与您所追求的足够接近......

    【讨论】:

    • 虽然我将 as.numeric(x[3]) * prices$Soybeans 更改为 as.numeric(x[2]) *,但我可以复制您的结果价格$大豆,因为我认为这是一个错字。我在原始数据中使用该解决方案时遇到问题,因为我在重塑数据时遇到错误(缺少聚合函数:默认为长度)并且数据框 weights.c 将所有商品作为整数返回,而不是数值。知道可能是什么原因吗?
    【解决方案2】:

    我会取消堆叠/重塑权重表中的项目,然后使用data.table 连接价格和权重。

    ## Generate data table for country weights:
    weights<-data.table(country=c(rep("Australia",2),rep("Zimbabwe",3)),
                        item=c("Wheat","Sugar","Wheat","Sugar","Soybeans"),
                        itemcode=c(1,2,1,2,3),
                        share=c(0.12,0.08,0.16,0.08,0.03),
                        key="item")
    
    ## Generate data table for price index:
    prices<-data.table(date=seq(as.Date("2005/1/1"),by="month",length.out=12),
                       Wheat=runif(12,80,160),
                       Sugar=runif(12,110,230),
                       Soybeans=runif(12,60,130))
    
    ## Get column names of all the food types:
    vars<-names(prices)[!names(prices) %in% "date"]    
    
    ## Unstack the items and create a "long" table:
    prices<-data.table(date=prices[,date], stack(prices,vars),key="ind")
    
    ## Rename the columns:
    setnames(prices,c("values","ind"),c("price","item"))
    
    prices[1:5]
    ##          date     price     item
    ## 1: 2005-01-01  88.25818 Soybeans
    ## 2: 2005-02-01  71.61261 Soybeans
    ## 3: 2005-03-01  77.91082 Soybeans
    ## 4: 2005-04-01 129.05806 Soybeans
    ## 5: 2005-05-01  74.63005 Soybeans
    
    ## Join the weights and prices tables, multiply the share by the price, and sum by country and date:
    weights[prices,allow.cartesian=T][,list(index=sum(share*price)),by=list(country,date)]
    
    ##       country       date    index
    ##  1:  Zimbabwe 2005-01-01 27.05711
    ##  2:  Zimbabwe 2005-02-01 34.72842
    ##  3:  Zimbabwe 2005-03-01 35.23615
    ##  4:  Zimbabwe 2005-04-01 39.05027
    ##  5:  Zimbabwe 2005-05-01 39.48388
    ##  6:  Zimbabwe 2005-06-01 33.43677
    ##  7:  Zimbabwe 2005-07-01 32.55172
    ##  8:  Zimbabwe 2005-08-01 34.86790
    ##  9:  Zimbabwe 2005-09-01 33.29748
    ## 10:  Zimbabwe 2005-10-01 38.31180
    ## 11:  Zimbabwe 2005-11-01 31.29709
    ## 12:  Zimbabwe 2005-12-01 40.70930
    ## 13: Australia 2005-01-01 21.07165
    ## 14: Australia 2005-02-01 27.47660
    ## 15: Australia 2005-03-01 27.03025
    ## 16: Australia 2005-04-01 29.34917
    ## 17: Australia 2005-05-01 31.95188
    ## 18: Australia 2005-06-01 26.22890
    ## 19: Australia 2005-07-01 24.58945
    ## 20: Australia 2005-08-01 27.44728
    ## 21: Australia 2005-09-01 27.02199
    ## 22: Australia 2005-10-01 31.58282
    ## 23: Australia 2005-11-01 24.42326
    ## 24: Australia 2005-12-01 31.70109
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-10
      • 2019-04-08
      • 2014-11-15
      • 1970-01-01
      相关资源
      最近更新 更多