我想通过匹配日期数据将补充信息从 df2 添加到 df1。
df1 是主要数据框:
x0 x1 x2 x3 x4 x5 ... x10000 Date
1 40 31.05 25.5 25.5 25.5 25 ... 33 2013-11-13
2 35 35.75 36.5 36.5 36.5 36.5 ... 29 2013-09-05
⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮
df2 是我想添加到 df1 的补充天气信息:
year month day maxtemp mintemp rainfall wind
2013 1 1 26.2 20.2 0 32.4
2013 1 2 22.9 20.3 0 10
2013 1 3 24.8 18.4 0 28.8
2013 1 4 26.6 18.3 0 33.5
2013 1 5 28.3 20.9 0 33.4
2013 1 6 28 21.6 0 32.8
2013 1 7 27.5 21.4 0 26.8
2013 1 8 42.3 20.9 0 25.5
2013 1 9 25 21.1 0 20.9
2013 1 10 25.4 20.2 0 14
⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮
我需要添加前述100天的maxtemp
,mintemp
,rainfall
并wind
从提取的数据df2
,对所述DF1每行的端部水平与由匹配year
,month
,day
的Date
在df1
。所以Date
是100当天和前99天,都在99天Date
。
预期输出:
x0 x1 x2 x3 x4 x5 ... x10000 Date max_t1...max_t100 min_t1...min_t100 rf1... rf100 w1 ... w100
1 40 31.05 25.5 25.5 25.5 25 ... 33 2013-01-01 26.2 ... 20.2 ... 0 ... 32.4...
2 35 35.75 36.5 36.5 36.5 36.5 ... 29 2013-01-03 24.8. ... 18.4 ... 0 ... 28.8
⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮
在哪里
max_t1, ..., max_t100 represent max temperature from day1 to day100(`Date` day);
min_t1, ..., min_t100 represent min temperature from day1 to day100(`Date` day);
rf1, ..., rf100 represent rainfall from day1 to day100(`Date` day);
w1, ..., w100 represent wind from day1 to day100(`Date` day).
这些是新添加的列名(所以总共会有 400 个新列)。
我假设df1中的Date列是datetime类型。如果不是,请转换它。
从这样的准备步骤开始:
在df2 中转换年/月/日列的索引(日期时间类型):
df2 = df2.set_index(pd.to_datetime(df2.year * 10000 + df2.month * 100
+ df2.day, format='%Y%m%d')).drop(columns=['year', 'month', 'day'])
设置天数,为其添加列:
nDays = 3
出于演示目的,我仅将其设置为3,但您可以将其更改为100或您希望的任何值。
为新列定义列名(首先导入 itertools):
cols = [ x + str(y) for x, y in itertools.product(
['max_t', 'min_t', 'rf', 'w'], range(1, nDays + 1)) ]
定义一个函数来为当前行生成附加列:
def fn(row):
d1 = row.Date
d2 = d1 + pd.Timedelta(nDays - 1, 'D')
return pd.Series(df2.loc[d1:d2].values.reshape((1, -1),
order='F').squeeze(), index=cols)
现在,整体的处理,可以在由单个指令,将上述功能的每一行并加入结果为原始数据帧:
df1 = df1.join(df1.apply(fn, axis=1))
相当简洁,而且在很大程度上是Pandasonic解决方案。
为了演示此解决方案的工作原理,我稍微更改了您的数据:
df1:
x0 x1 x2 x3 Date
0 40 31.05 25.5 25.5 2013-01-03
1 35 35.75 36.5 36.5 2013-01-07
df2(初始内容):
year month day maxtemp mintemp rainfall wind
0 2013 1 1 26.2 20.2 0 32.4
1 2013 1 2 22.9 20.3 0 10.0
2 2013 1 3 24.8 18.4 1 28.8
3 2013 1 4 26.6 18.3 2 33.5
4 2013 1 5 28.3 20.9 3 33.4
5 2013 1 6 28.0 21.6 4 32.8
6 2013 1 7 27.5 21.4 5 26.8
7 2013 1 8 42.3 20.9 6 25.5
8 2013 1 9 25.0 21.1 7 20.9
9 2013 1 10 25.4 20.2 8 14.0
df2(转换后):
maxtemp mintemp rainfall wind
2013-01-01 26.2 20.2 0 32.4
2013-01-02 22.9 20.3 0 10.0
2013-01-03 24.8 18.4 1 28.8
2013-01-04 26.6 18.3 2 33.5
2013-01-05 28.3 20.9 3 33.4
2013-01-06 28.0 21.6 4 32.8
2013-01-07 27.5 21.4 5 26.8
2013-01-08 42.3 20.9 6 25.5
2013-01-09 25.0 21.1 7 20.9
2013-01-10 25.4 20.2 8 14.0
添加新列后,df1包含:
x0 x1 x2 x3 Date max_t1 max_t2 max_t3 min_t1 min_t2 \
0 40 31.05 25.5 25.5 2013-01-03 24.8 26.6 28.3 18.4 18.3
1 35 35.75 36.5 36.5 2013-01-07 27.5 42.3 25.0 21.4 20.9
min_t3 rf1 rf2 rf3 w1 w2 w3
0 20.9 1.0 2.0 3.0 28.8 33.5 33.4
1 21.1 5.0 6.0 7.0 26.8 25.5 20.9
如果要从当前日期前100 天获取添加的行,请更改fn函数中设置两个“边界日期”的方式。就像是:
def fn(row):
d1 = row.Date - pd.Timedelta(nDays, 'D')
d2 = row.Date - pd.Timedelta(1, 'D')
return pd.Series(df2.loc[d1:d2].values.reshape((1, -1), order='F')
.squeeze(), index=cols)
如果您的df2包含某些日期的多行,则将df1与df2 连接会导致输出行数增加。
如果DF2已经有一段日子,例如有3行的一个排从DF1与此日期的结果将只包含3行(具有相同的日期)。
为了避免这种情况,您必须“抑制”这种重复。
最初我想过df2 = df2.drop_duplicates(...),但是您写道,一行可以包含一组值和另一行 - 另一组,因此我们不能随意保留一行并删除其他行(从同一日期开始) )。
此问题的一种可能解决方案是,在创建“日期索引”之后,您应该:
执行此操作的代码是:
df2 = df2.groupby(level=0).mean()
然后就可以join了(如上所述),输出行数应该不会增长。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句