R:具有非数字索引的嵌套循环

时间:2015-10-25 16:56:01

标签: r vectorization

我是一名政治学学生并且学习R.我有一个嵌套循环的问题,我的一个索引是非数字的。 我有一个数据框pwt,其中包含世界上每个国家/地区(country列)和1950年至2011年每年(第year列)的一些发展指标,其中包括GDP。 我想添加一个列,其中包含从一年到下一年的GDP变化百分比。

这是我得到的错误:

Error in `[<-.factor`(`*tmp*`, iseq, value = numeric(0)):  replacement has length zero

GDPgrowth = rep("NA", length(pwt$country))
pwt <- cbind.data.frame(pwt, GDPgrowth)
countries <- unique(pwt$country)
for(i in countries)  # for each country
{
  for(j in 1951:2011) # for each year
  {
    pwt[pwt$country == i & pwt$year == j,"GDPgrowth"] = (pwt[pwt$country == i 
& pwt$year == j,"rdgpo"]/pwt[pwt$country == i & pwt$year == j-1,"rdgpo"] - 
1)*100
  }
}

我出错了什么?

4 个答案:

答案 0 :(得分:3)

欢迎使用Stack Overflow!

对于这种滚动/物件等,您可以使用zoodplyrdata.table。我个人更喜欢后者,因为它具有大型数据集的灵活性和(运行)速度。比。使用循环,这些通常会更快,语法更方便。

假设您的数据看起来像这样(数字明显构成):

country year rgdp
USA     1991 1000
USA     1992 1200
USA     1993 1500
SWE     1991 1000
SWE     1992 900
SWE     1993 2000

您可以使用data.table的shift来计算超前/滞后值的值。在这种情况下:

library(data.table)

pwt <- as.data.table(list(country=c("USA", "USA", "USA", "SWE", "SWE", "SWE"),
                          year=c(1991, 1992, 1993, 1991, 1992, 1993),
                          rgdp=c(1000, 1200, 1500, 1000, 900, 2000)))

pwt[, growth := rgdp/shift(rgdp, n=1, type="lag") - 1, by=c("country")]

给出:

country year rgdp growth
USA     1991 1000 NA
USA     1992 1200 0.200000
USA     1993 1500 0.250000
SWE     1991 1000 NA
SWE     1992 900 -0.100000
SWE     1993 2000 1.222222

答案 1 :(得分:2)

另一种方法是使用基座diff中的R。这用于计算立即值之间的差异

difference<-c(0,diff(pwd$gdp))

这会让你在连续的GDP之间找到差异,你可以轻松地用它来找到百分比。

PS:SO是为了帮助人们,而不是提供精确的解决方案和勺子饲料。因此,这个答案只是指向一个方向,而不是给你准确的解决方案。

答案 2 :(得分:0)

你也可以避免循环:

p <- pwd[, c('country', 'year', 'rdgpo')]
p$year <- p$year + 1
colnames(p)[3] <- 'rdgpo_prev'

pwd <- merge(pwd, p, all.x=TRUE)
pwd$GDPgrowth <- 100 * ((pwd$rdgpo/pwd$rdgpo_prev) -1)
pwd$rdgpo_prev <- NULL

答案 3 :(得分:0)

出于同样的原因,使用dplyr可以实现避免循环的另一个方便的解决方案。

# Install and data download -----------------------------------------------

# World Bank Data pkg
install.packages('WDI')
require(WDI)

#' Source data
#' NYGDPMKTPCD correspond to "GDP, PPP (constant 2005 international $)"
#' Check WDIsearch() for codes
pwt <- WDI(country = "all", indicator = "NY.GDP.MKTP.PP.CD",
           start = 1951, end = 2011, extra = FALSE, cache = NULL)

# Percentage change on panel data -----------------------------------------

library(dplyr)
pwt <- pwt %>%
    group_by(country) %>%
    arrange(year) %>%
    mutate(pct.chg = 100 * 
               ((NY.GDP.MKTP.PP.CD - lag(NY.GDP.MKTP.PP.CD))/lag(NY.GDP.MKTP.PP.CD)))

作为一个侧面点,我建议,根据SO指南,您提供可重复的示例。在主要的公共可用统计数据库(欧盟统计局,经合组织,世界银行等)方面,有R包装和教程可以毫不费力地获取所需的数据。在上面的示例中,我使用WDI包来获取世界银行数据。

修改

最后,如果你坚持在循环中制作东西,你可以这样做:

for (i in unique(pwt$country))  {
    # Assuming that years are incomplete
    for (j in unique(pwt$year[pwt$country == i])) {
        # As the DF is simple i simply used column numbers
        pwt[which(
            pwt$year == j & 
                pwt$country == i) +1 ,6] <- 100 * ((pwt[which(pwt$year == j & 
                                                                  pwt$country == i)  +1 ,3]
                                                    - pwt[which(pwt$year == j & 
                                                                    pwt$country == i),3]) 
                                                   / abs(pwt[which(pwt$year == j & 
                                                                       pwt$country == i),3]))
    }
}

解决方案可能不那么明确,但我想强调需要为{strong>年和国家的每个组合选择正确的行,{{1声明。

基准

循环方法似乎效率很低:

which

上面的基准功能

require(microbenchmark)
microbenchmark(dpl_sol(), bse_sol(), times = 1)
Unit: milliseconds
      expr         min          lq        mean      median          uq         max neval
 dpl_sol()    21.26792    21.26792    21.26792    21.26792    21.26792    21.26792     1
 bse_sol() 94573.05671 94573.05671 94573.05671 94573.05671 94573.05671 94573.05671     1