R语言for循环提取data.table元素按国家年份匹配数据异常如何解决
问题原因分析
你写的代码核心错误有3处:
- 从dt2中取年份对应列的语法错误:data.table的j位置默认会将括号内的内容当作表达式计算,你写
(1+i)返回的就是1+i的数值,最后一次循环i=6时结果为7,所以全表index都被赋值为7。 - dt1的date字段没有转换为正确的日期格式:你原始的日期字符串是
年-日-月格式,没有指定format参数直接用as.Date转换会生成NA,条件判断全部失效。 - 代码中
countries变量没有预先定义,运行会直接报错。
另外双层for循环完全不符合data.table的设计逻辑,数据量稍大时运行效率会非常低。
推荐解决方案(最优实现)
先把dt2从宽表转为长表,直接通过国家+年份关联赋值,代码简洁且效率极高:
library(data.table) # 1. 预处理dt1的日期格式,提取匹配用的年份字段 dt1[, date := as.Date(date, format = "%Y-%d-%m")] dt1[, year := format(date, "%Y")] # 2. dt2宽表转长表,适配关联逻辑 dt2_long <- melt(dt2, id.vars = "country", variable.name = "year", value.name = "index") # 3. 关联更新dt1的index字段 dt1[dt2_long, on = .(country, year), index := i.index] # 可选:删除中间生成的year字段 dt1[, year := NULL]
运行后dt1的结果和你预期完全一致:
country date index 1: Argentina 2012-12-25 0.25 2: Brazil 2015-05-21 0.63 3: United States 2017-01-06 0.32
原循环代码的修正版
如果你坚持要使用循环实现,可按以下方式修改核心赋值逻辑:
library(data.table) # 预处理:定义变量、转换日期格式 countries <- unique(dt1$country) years <- as.character(2012:2017) dt1[, date := as.Date(date, format = "%Y-%d-%m")] # 修正循环赋值逻辑 for(i in seq_along(years)){ for(j in countries){ dt1[country == j & as.integer(format(date, "%Y")) == as.integer(years[i]), index := dt2[country == j, get(years[i])]] } }
内容的提问来源于stack exchange,提问作者Odysseus
相关产品推荐
相关产品推荐

