Pandas 重采样不求和

0 投票
1 回答
1256 浏览
提问于 2025-04-17 15:04

我有一个 pandas 数据框,里面包含了 461 支股票的收盘价格。

In [43]: pdata
Out[43]: 
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 3418 entries, 2000-01-03 00:00:00 to 2013-02-06 00:00:00
Columns: 461 entries, AKM to ZIM
dtypes: float64(461)

我正在根据过去 130 天的收益率对这些股票进行排名,并选择表现最好的前 10 支股票。

In [44]: mom_ret = pdata.shift(1).pct_change(130)

In [45]: rank = mom_ret.rank(axis=1,ascending=False,method='first')

In [46]: rank[rank<=10]=1

In [47]: rank[rank>10]=0

如果我把每一行的数值相加,它们的总和都是 10,这正是我预期的结果。

In [48]: x=rank.groupby(rank.sum(axis=1))

In [49]: x.sum()
Out[49]: 
<class 'pandas.core.frame.DataFrame'>
Index: 1 entries, 10.0 to 10.0          # all rows sum to 10 as expected.
Columns: 461 entries, AKM to ZIM
dtypes: float64(461)

然后我对数据框进行了重新采样,如下所示:

In [50]: port = rank.resample('20B', how='first')

In [51]: y=port.groupby(port.sum(axis=1))

但是现在当我把每一行的数值相加时,它们的总和却不是 10 了?

In [52]: y.sum()
Out[52]: 
<class 'pandas.core.frame.DataFrame'>
Index: 4 entries, 10.0 to 13.0          # 4 entries ranging between 10 and 13??
Columns: 461 entries, AKM to ZIM
dtypes: float64(461)

我不明白为什么会这样。是我做错了什么,还是这是个 bug?

我刚刚意识到,如果我把 NaN(缺失值)替换成 0,就没有这个问题了。

In [67]: rank=rank.fillna(0)

In [68]: x=rank.groupby(rank.sum(axis=1))

In [69]: x.sum()
Out[69]: 
<class 'pandas.core.frame.DataFrame'>
Index: 2 entries, 0.0 to 10.0     # 2 entries, 0 and 10
Columns: 461 entries, AKM to ZIM
dtypes: float64(461)

In [70]: port = rank.resample('20B', how='first')

In [71]: y=port.groupby(port.sum(axis=1))

In [72]: y.sum()
Out[72]: 
<class 'pandas.core.frame.DataFrame'>
Index: 2 entries, 0.0 to 10.0    # 2 entries again, 0 and 10
Columns: 461 entries, AKM to ZIM
dtypes: float64(461)

但是我希望在重新采样时不把 NaN 填充为 0。这可能吗?谢谢。

1 个回答

3

你看到这种情况的原因是因为 how=first 会从每一列中取第一个不是空值(na)的数据。这就是为什么把空值(NAs)填成0会得到正确结果的原因。如果你想要的结果是不填空值的情况下得到第一个数据,你可以给 how 传一个自定义的函数,这样就可以无论是不是空值都取第一个数据:

In [47]: port = rank.resample('20B', how=lambda x: x.ix[0])

In [48]: y=port.groupby(port.sum(axis=1))

In [49]: y.sum()
Out[49]: 
<class 'pandas.core.frame.DataFrame'>
Index: 1 entries, 10.0 to 10.0
Columns: 461 entries, AKM to ZIM
dtypes: float64(461)

撰写回答