pandas 数据框替换问题
我有一个数据框(df)
df:
date shares symbol date2
0 20120614 1100 AAT.N NaN
1 20120615 1100 AAT.N NaN
2 20120616 1100 AAT.N NaN
3 20120617 1100 AAT.N NaN
4 20030405 800 ABT.N NaN
5 20030406 800 ABT.N NaN
6 20030407 800 ABT.N NaN
...
#This is what I want:
df:
date shares symbol date2
0 20120614 1100 AAT.N 20120615
1 20120615 1100 AAT.N 20120616
2 20120616 1100 AAT.N 20120617
3 20120617 1100 AAT.N NaN
4 20030405 800 ABT.N 20030406
5 20030406 800 ABT.N 20030407
6 20030407 800 ABT.N NaN
...
我想把 df.ix[0]['date2'] 替换成 df.ix[1]['date2'],这个操作是针对每个符号(symbol)进行的,因为符号在数据框中是变化的,所以不能直接对整个数据框进行操作。
我打算通过循环来实现,如果当前的符号和下一个符号匹配的话:
df.ix[i]['symbol'] == df.ix[i+1]['symbol']
我就把 NaN 替换成对应的日期。
我试过:
df.ix[i]['date2'] = df.ix[i+1]['date'] ##This failed.
然后我又试了:
a = df.ix[i+1]['date']
df.replace({'date2': i}, a)
###This failed as well
在这里有没有什么建议呢?
1) 最好的方法来完成这个任务是什么?
2) 基础问题:如何在 pandas 数据框中替换 NaN(或者其他数字)?
谢谢。
3 个回答
0
我可能会这样做:
>>> df
date shares symbol date2
0 20120614 1100 AAT.N NaN
1 20120615 1100 AAT.N NaN
2 20120616 1100 AAT.N NaN
3 20120617 1100 AAT.N NaN
4 20030405 800 ABT.N NaN
5 20030406 800 ABT.N NaN
6 20030407 800 ABT.N NaN
>>> same_symbols = df['symbol'] == df['symbol'].shift(-1)
>>> df['date2'][same_symbols] = df['date'].shift(-1)
>>> df
date shares symbol date2
0 20120614 1100 AAT.N 20120615
1 20120615 1100 AAT.N 20120616
2 20120616 1100 AAT.N 20120617
3 20120617 1100 AAT.N NaN
4 20030405 800 ABT.N 20030406
5 20030406 800 ABT.N 20030407
6 20030407 800 ABT.N NaN
这段代码是用来找出每一行之间相同的符号的位置:
>>> same_symbols
0 True
1 True
2 True
3 False
4 True
5 True
6 False
Name: symbol, Dtype: bool
然后在这些位置上应用偏移的日期:
>>> df['date'].shift(-1)
0 20120615
1 20120616
2 20120617
3 20030405
4 20030406
5 20030407
6 NaN
Name: date, Dtype: float64
这段代码假设符号数据是连续的,并且已经排好序(如果不是这样的话,调整一下也很简单)。
另外,你也可以使用 groupby
,然后对每一组进行操作,最后再把结果组合起来。
1
为了和DSM的布尔解决方案进行比较,这里有一个简单快捷的groupby解决方案!
grouped = df.groupby('symbol')
for _, group in grouped:
df1['date2'][group.index] = group.shift(-1)['date']
3
这里有一个一行代码的解决方案,可能是最“简单明了”的:
In [8]: df['date2'] = df.groupby('symbol').apply(lambda x: x['date'].shift(-1))
In [9]: df
Out[9]:
date shares symbol date2
0 20120614 1100 AAT.N 20120615
1 20120615 1100 AAT.N 20120616
2 20120616 1100 AAT.N 20120617
3 20120617 1100 AAT.N NaN
4 20030405 800 ABT.N 20030406
5 20030406 800 ABT.N 20030407
6 20030407 800 ABT.N NaN