我是一名政治学学生并且学习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
}
}
我出错了什么?
答案 0 :(得分:3)
欢迎使用Stack Overflow!
对于这种滚动/物件等,您可以使用zoo,dplyr或data.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