【问题标题】:In each row of pandas, starting at the first non-NaN a window of X values remains untouched while all other values are NaN在熊猫的每一行中,从第一个非 NaN 开始,X 值的窗口保持不变,而所有其他值都是 NaN
【发布时间】:2021-01-21 21:48:49
【问题描述】:

StackOverflow 的公民,

我目前正在对可能有数百万行长的数据框运行迭代。在我的数据框的每一行中,我都有领先的 NaN(所需),然后是值。我只想在每行中有 X 个值,然后是 NaN。 实际上我想要一个只有 X 值的窗口,从第一个非 NaN 开始,行中的所有其他位置都是 NaN。

我的解决方案很慢。此外,我没有发现类似的问题有足够的帮助(最关心的只是第一个/最后一个 NaN)。

窗口大小为 3 的示例:

import pandas as pd
import numpy as np

x = 3

data = {'2018Q3': [0,   np.nan,   np.nan,      np.nan,      np.nan], 
        '2018Q4': [1,      np.nan,   np.nan,       np.nan,    10],
        '2019Q1': [2,        3,    np.nan,      np.nan, 12],
        '2019Q2': [3,        4,    np.nan,      8,         14],
        '2019Q3': [4,        5,    np.nan,      9,         22]}  

df = pd.DataFrame.from_dict(data) 
print(df)

      2018Q3  2018Q4  2019Q1  2019Q2  2019Q3
0     0.0     1.0     2.0     3.0     4.0
1     NaN     NaN     3.0     4.0     5.0
2     NaN     NaN     NaN     NaN     NaN
3     NaN     NaN     NaN     8.0     9.0
4     NaN    10.0    12.0    14.0    22.0

结果应如下所示:

   2018Q3  2018Q4  2019Q1  2019Q2  2019Q3
0     0.0     1.0     2.0     NaN     NaN
1     NaN     NaN     3.0     4.0     5.0
2     NaN     NaN     NaN     NaN     NaN
3     NaN     NaN     NaN     8.0     9.0
4     NaN    10.0    12.0    14.0     NaN

我的解决方案:

def cut_excess_forecast(num_x, dataf): 
    Total_Col = len(dataf.columns.values) # total columns
    df_NEW = pd.DataFrame()
    for index, row in dataf.iterrows():
        nas = row.isnull().sum(axis =0)  # number of nulls
        good_data = nas +  num_x # gives number of columns that should be untouched
        if good_data >= Total_Col: # if number of columns to not be touched > available columns, pass
            pass # all data available is needed
        else:
            cutoff = Total_Col-good_data 
            row[-cutoff:] = np.nan #change to NaN excess columns in this row

        df_NEW = df_NEW.append(row.copy()) #append changed row to new index
    df_NEW.index = dataf.index #move over original index to the new dataframe
    return df_NEW.copy()

df2 = cut_excess_forecast(x, df)
print(df2)

排序是允许的,只要索引未被触及。 提前干杯和感谢。

【问题讨论】:

    标签: python pandas nan


    【解决方案1】:

    试试:

    df.where(df.notna().cumsum(1)<4)
    

    输出:

       2018Q3  2018Q4  2019Q1  2019Q2  2019Q3
    0     0.0     1.0     2.0     NaN     NaN
    1     NaN     NaN     3.0     4.0     5.0
    2     NaN     NaN     NaN     NaN     NaN
    3     NaN     NaN     NaN     8.0     9.0
    4     NaN    10.0    12.0    14.0     NaN
    

    解释

    1. df.notna()False 屏蔽NaN 值,用True 屏蔽非NaN 值。
       2018Q3  2018Q4  2019Q1  2019Q2  2019Q3
    0    True    True    True    True    True
    1   False   False    True    True    True
    2   False   False   False   False   False
    3   False   False   False    True    True
    4   False    True    True    True    True
    
    1. 使用cumsum(1) 的链将从左到右计算行上的非NaN 值。
       2018Q3  2018Q4  2019Q1  2019Q2  2019Q3
    0       1       2       3       4       5
    1       0       0       1       2       3
    2       0       0       0       0       0
    3       0       0       0       1       2
    4       0       1       2       3       4
    
    1. 然后我们与&lt;4 进行比较以屏蔽计数超过阈值4False
       2018Q3  2018Q4  2019Q1  2019Q2  2019Q3
    0    True    True    True   False   False
    1    True    True    True    True    True
    2    True    True    True    True    True
    3    True    True    True    True    True
    4    True    True    True    True   False
    
    1. 最后将 .where 包裹起来,用 np.NaN 掩盖这些单元格。

    【讨论】:

    • 美丽的答案和解释。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-11
    • 1970-01-01
    • 2012-06-13
    • 2021-11-12
    • 1970-01-01
    • 2021-05-01
    • 1970-01-01
    相关资源
    最近更新 更多