我有一个DataFrame,其中多行跨越每个索引.例如,第一个索引具有这样的结构:
df = pd.DataFrame([["A", "first", 1.0, 1.0, np.NaN],
[np.NaN, np.NaN, 2.0, np.NaN, 2.0],
[np.NaN, np.NaN, np.NaN, 3.0, 3.0]],
columns=["ID", "Name", "val1", "val2", "val3"],
index=[0, 0, 0])
Out[4]:
ID Name val1 val2 val3
0 A first 1 1 NaN
0 NaN NaN 2 NaN 2
0 NaN NaN NaN 3 3
Run Code Online (Sandbox Code Playgroud)
我想对每列进行排序/排序,使得NaN
s位于该给定索引处每列的底部 - 结果如下所示:
ID Name val1 val2 val3
0 A first 1 1 2
0 NaN NaN 2 3 3
0 NaN NaN NaN NaN NaN
Run Code Online (Sandbox Code Playgroud)
更明确的示例可能如下所示:
df = pd.DataFrame([["A", "first", 1.0, 1.0, np.NaN],
[np.NaN, np.NaN, 2.0, np.NaN, 2.0],
[np.NaN, np.NaN, np.NaN, 3.0, 3.0],
["B", "second", 4.0, 4.0, np.NaN],
[np.NaN, np.NaN, 5.0, np.NaN, 5.0],
[np.NaN, np.NaN, np.NaN, 6.0, 6.0]],
columns=[ "ID", "Name", "val1", "val2", "val3"],
index=[0, 0, 0, 1, 1, 1])
Out[5]:
ID Name val1 val2 val3
0 A first 1 1 NaN
0 NaN NaN 2 NaN 2
0 NaN NaN NaN 3 3
1 B second 4 4 NaN
1 NaN NaN 5 NaN 5
1 NaN NaN NaN 6 6
Run Code Online (Sandbox Code Playgroud)
期望的结果看起来像这样:
ID Name val1 val2 val3
0 A first 1 1 2
0 NaN NaN 2 3 3
0 NaN NaN NaN NaN NaN
1 B second 4 4 5
1 NaN NaN 5 6 6
1 NaN NaN NaN NaN NaN
Run Code Online (Sandbox Code Playgroud)
我在这个数据帧中有数千行,每个索引最多包含几百行.to_csv
在数据框架中,我期望的结果将非常有用.
我试图sort_values(['val1','val2','val3'])
在整个数据框架上使用,但这导致索引变得无序.我试图遍历每个索引并进行排序,但这也不会限制NaN
每个索引列的底部.我也尝试过fillna
另一个值,比如0,但我在这里也没有成功.
虽然我肯定使用它错了,但na_position
参数in sort_values
并没有产生预期的结果,尽管看起来这可能是想要的.
编辑:
最后的df索引不需要像我的第二个例子那样按数字顺序排列.
通过改变ignore_index
到False
以@的Leb第三代码块的单线,
pd.concat([df[col].sort_values().reset_index(drop=True) for col in df], axis=1, ignore_index=True)
Run Code Online (Sandbox Code Playgroud)
至
pd.concat([df[col].sort_values().reset_index(drop=True) for col in df], axis=1, ignore_index=False)
Run Code Online (Sandbox Code Playgroud)
通过为给定索引中的所有行创建临时df,我能够完成这项工作 - 不是很漂亮,但它会按照我需要的方式来命令.如果有人(当然)有更好的方法,请告诉我.
new_df = df.ix[0]
new_df = pd.concat([new_df[col].sort_values().reset_index(drop=True) for col in new_df], axis=1, ignore_index=False)
max_index = df.index[-1]
for i in range(1, max_index + 1):
tmp = df.ix[i]
tmp = pd.concat([tmp[col].sort_values().reset_index(drop=True) for col in tmp], axis=1, ignore_index=False)
new_df = pd.concat([new_df,tmp])
In [10]: new_df
Out[10]:
ID Name val1 val2 val3
0 A first 1 1 2
1 NaN NaN 2 3 3
2 NaN NaN NaN NaN NaN
0 B second 4 4 5
1 NaN NaN 5 6 6
2 NaN NaN NaN NaN NaN
Run Code Online (Sandbox Code Playgroud)
我知道 github 上已经讨论过将 nan 推向边缘的问题。对于您的特定框架,我可能会在 Python 级别手动完成,而不必太担心性能。就像是
>>> df.groupby(level=0, sort=False).transform(lambda x: sorted(x,key=pd.isnull))
ID Name val1 val2 val3
0 A first 1 1 2
0 NaN NaN 2 3 3
0 NaN NaN NaN NaN NaN
1 B second 4 4 5
1 NaN NaN 5 6 6
1 NaN NaN NaN NaN NaN
Run Code Online (Sandbox Code Playgroud)
应该管用。请注意,由于sorted
是一种稳定排序,并且我们将pd.isnull
其用作键(其中 False < True),因此我们将 NaN 推到末尾,同时保留剩余对象的顺序。另请注意,这里我仅根据索引进行分组;我们也可以根据我们想要的任何内容进行分组。
归档时间: |
|
查看次数: |
669 次 |
最近记录: |