如何解决如何基于一级掩码填充多索引数据框
import pandas as pd
from itertools import product
arrays = [['bar','baz','foo'],range(4)]
tuples = list(product(*arrays))
index = pd.MultiIndex.from_tuples(tuples,names=['first','second'])
multi_ind=pd.DataFrame(np.random.randn(6,len(tuples)),index=range(6),columns=index)
有些值是nans:
multi_ind.loc[3,('bar',2)]=np.nan
multi_ind.loc[3,3)]=np.nan
multi_ind.loc[4,1)]=np.nan
对于'bar'
,我想填写所有nans的最后期望,如以下所述:
Forward fill all except last value in python pandas dataframe
mask=multi_ind['bar']
last_valid_column_per_row = mask.apply(pd.Series.last_valid_index,axis=1)
mask=mask.apply(lambda series:series[:int(last_valid_column_per_row.loc[series.name])].ffill(),axis=1)
然后,我想使用与bar(从{{到最后一个有效索引)相同的逻辑,也ffill()
也使用其他第一层(例如baz
,foo
) 1}}),并且我想同时为df['bar']
nan
的任何值设置一个nan
如何有效地实现这一目标?
现在我正在执行以下操作,但是速度很慢...
bar
解决方法
基于 last_valid_index 的代码(在指定的帖子中)实际上 沿给定轴填充 NaN :
- 没有初始 NaN 单元格(填充没有先前的值 作为来源)
- 没有跟踪 NaN 细胞(无论其数量如何), 由于 last_valid_index 而终止了操作 在 NaN s的尾随连续序列之前,
但是如果您对此安排感到满意,那就顺其自然吧。
我通过以下更简洁的方式创建了测试DataFrame:
arrays = [['bar','baz','foo'],range(4)]
cols = pd.MultiIndex.from_product(arrays,names=['first','second'])
np.random.seed(2)
arr = np.arange(1,6 * 12 + 1,dtype=float).reshape(6,-1)
# Where to put NaN (x / y)
ind = (np.array([0,1,2,3,4,5,5]),np.array([1,6,10,11]))
arr[ind] = np.nan
multi_ind = pd.DataFrame(arr,columns=cols)
包含以下内容:
first bar baz foo
second 0 1 2 3 0 1 2 3 0 1 2 3
0 1.0 NaN NaN 4.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0
1 13.0 14.0 15.0 16.0 17.0 18.0 NaN 20.0 21.0 22.0 23.0 24.0
2 25.0 NaN 27.0 NaN 29.0 NaN 31.0 32.0 33.0 34.0 35.0 36.0
3 37.0 38.0 39.0 40.0 41.0 42.0 43.0 44.0 45.0 46.0 NaN 48.0
4 49.0 50.0 NaN NaN 53.0 54.0 55.0 56.0 57.0 58.0 59.0 60.0
5 61.0 62.0 63.0 64.0 65.0 66.0 67.0 68.0 69.0 70.0 NaN NaN
要获得结果,请运行:
result = multi_ind.stack(level=0).apply(
lambda row: row[: row.last_valid_index() + 1].ffill(),axis=1)\
.unstack(level=1).swaplevel(axis=1).reindex(columns=multi_ind.columns)
请注意,您不需要 last_valid_column_per_row 。 传递 axis = 1 即可对行进行操作,而不是 列(如指示的帖子中所示)。
结果是:
first bar baz foo
second 0 1 2 3 0 1 2 3 0 1 2 3
0 1.0 1.0 1.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0
1 13.0 14.0 15.0 16.0 17.0 18.0 18.0 20.0 21.0 22.0 23.0 24.0
2 25.0 25.0 27.0 NaN 29.0 29.0 31.0 32.0 33.0 34.0 35.0 36.0
3 37.0 38.0 39.0 40.0 41.0 42.0 43.0 44.0 45.0 46.0 46.0 48.0
4 49.0 50.0 NaN NaN 53.0 54.0 55.0 56.0 57.0 58.0 59.0 60.0
5 61.0 62.0 63.0 64.0 65.0 66.0 67.0 68.0 69.0 70.0 NaN NaN
详细信息:
-
stack(level=0)
-将 bar , baz 和 foo “片段”放入 在连续的行中。 -
apply(….ffill(),axis=1)
-每行填充,无尾随 NaN 的序列(如果有)。请注意,我添加了 +1 在结果中包含最后一个非NaN 值。否则最后 列将被删除。 -
unstack(level=1)
-恢复先前的(“宽”)排列, 但不幸的是,列MultiIndex级别的顺序是相反的。 -
swaplevel(axis=1)
-恢复列级别的原始顺序, 但不幸的是,列名的顺序是错误的。 -
reindex(…)
-恢复原始列顺序。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。