如何对DataFrame的每一行按字母排序并将NaN移至右侧?
问题描述
我的DataFrame如下:
0 1 2 3 4 5 6 ... 10 11 12 13 14 15 16 0 NaN NaN NaN TUR NaN ACP HEX ... NaN NaN HEX HEX NaN NaN NaN 1 NaN NaN NaN TUR NaN ACP HEX ... NaN NaN NaN HEX HEX HEX NaN 2 NaN NaN NaN NaN NaN TUR TUR ... HEX HEX NaN NaN HEX HEX HEX 3 NaN NaN NaN NaN NaN TUR NaN ... HEX NaN NaN HEX HEX HEX NaN 4 NaN NaN NaN NaN TUR NaN TUR ... HEX NaN NaN NaN HEX HEX HEX ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... 32607 NaN NaN NaN TUR NaN ACP HEX ... NaN HEX NaN NaN NaN NaN NaN 32608 NaN NaN NaN TUR NaN ACP HEX ... NaN HEX NaN NaN NaN NaN NaN 32609 NaN NaN NaN TUR NaN ACP HEX ... NaN HEX NaN NaN NaN NaN NaN 32610 NaN NaN NaN TUR NaN ACP HEX ... NaN HEX NaN NaN NaN NaN NaN 32611 NaN NaN NaN TUR NaN ACP HEX ... NaN HEX NaN NaN NaN NaN NaN
需要对每一行按字母顺序排序,将所有NaN移至右侧,所有字符串移至左侧。
解决方案
方法1:逐行排序(简单直观)
直接用apply对每行执行排序,利用NaN在排序逻辑中默认靠后的特性,配合自定义排序键实现需求:
import pandas as pd # 假设你的DataFrame变量名为df df_sorted = df.apply(lambda row: sorted(row, key=lambda x: (pd.isna(x), x)), axis=1) df_sorted = pd.DataFrame(df_sorted.tolist(), columns=df.columns)
- 排序键
(pd.isna(x), x)先判断元素是否为NaN:True(即NaN)会被排在False之后; - 非
NaN的字符串则按字母顺序排序; - 最后将排序后的列表重新转为DataFrame,保留原列名。
方法2:矢量化优化(适合大数据量)
如果处理的是上万行的大数据集,apply逐行处理效率偏低,可以用以下更高效的方式:
# 提取每行非NaN值并按字母排序 non_nan_sorted = df.apply(lambda x: sorted(x.dropna()), axis=1) # 计算每行需要补充的NaN数量 nan_counts = df.isna().sum(axis=1) # 拼接排序后的字符串和对应数量的NaN sorted_rows = non_nan_sorted.apply(lambda x: x + [float('nan')] * nan_counts.loc[x.name]) # 转为最终DataFrame df_sorted = pd.DataFrame(sorted_rows.tolist(), columns=df.columns)
这种方法先单独处理非NaN值的排序,再补充对应数量的NaN,避免了对NaN元素的无效排序操作,速度更快。
效果验证
以第一行为例,排序后结果为:ACP, HEX, HEX, HEX, TUR, NaN, NaN, ..., NaN,完全符合字母排序且所有NaN移至右侧的要求。
内容的提问来源于stack exchange,提问作者Tony Sirico
相关产品推荐
相关产品推荐

