首页 > 解决方案 > 数据框:在列上移动值

问题描述

我的s_x列中有一个包含一些 NaN 值的数据框。如果NaN其中存在值,我希望它们位于最后一列。

示例:给定s_x列中的值,[Nan, 1, Nan, 2]我希望这些值在列上向左移动以导致[1, 2, NaN, NaN]

示例 2:

示例 DF

我目前的解决方案非常慢,因为我:

如何改进以下功能?值的顺序(从低到高)需要保持不变。每个值只能在一行的s_x列中找到一次。

我知道通过解析到列表并返回来“离开熊猫逻辑”在性能方面存在问题,并且正在考虑尝试使用 lambda 函数来完成它,但没有得到任何结果。

我当前的代码作为一个最小的工作示例:

import pandas as pd
import numpy as np

def shift_values(df, leading_chars):
    """Shifts all values in columns with common leading chars to the left if there are NaN values.
    
    Example:   Given a row of [NaN, 1, NaN, 2]
    the values are shifted to [1, 2, NaN, NaN]
    
    """
    cols = [c for c in list(df.columns) if c[:len(leading_chars)] == leading_chars] 

    for index, row in df.iterrows():
        # create list without NaN values
        values = [v for v in row[cols] if not pd.isna(v)] 
        # pad with NaN to get correct number of values again
        values += [np.nan] * (len(cols) - len(values))  

        # overwrite row values with modified list
        for i, c in enumerate(cols): 
            row[c] = values[i]

        # overwrite row in the dataframe
        df.iloc[index] = row

    return df 

mylist = [["key", "s_1", "s_2", "s_3", "s_4"],
          [1, np.nan, 1, 2, np.nan],
          [1, 10, 20, 25, np.nan],
          [1, 10, np.nan, 25, np.nan]
         ]
df = pd.DataFrame(mylist[1:], columns=mylist[0])

print("______ PREVIOUS ______")
print(df.head())

df = shift_values(df, 's_')
print("______ RESULT ______")
print(df.head())

标签: pythonpandasdataframenumpy

解决方案


尝试:

df = df.transform(sorted, key=pd.isna, axis=1)
print(df)

印刷:

   key   s_1   s_2   s_3  s_4
0  1.0   1.0   2.0   NaN  NaN
1  1.0  10.0  20.0  25.0  NaN
2  1.0  10.0  25.0   NaN  NaN

编辑:如果列不相邻:

x = df.filter(regex=r"^s_")

df.loc[:, x.columns] = df.loc[:, x.columns].transform(
    sorted, key=pd.isna, axis=1
)
print(df)

推荐阅读