为最接近数据集中所选列的每一行添加第一个非 Nan 的新列 Python

Adding new column with first non Nan for each row closest to a chosen column from a dataset Python

你好,我想从给定的数据集(我在这里称之为“df”)创建一个新列,每行的第一个非 Nan 和最接近给定的列

例如,我有一个数据框,年份为 2009 2010 2011 2012 2013 2014。我想为每一行找到第一个非 Nan 值,但从 2011 年开始!

所以这是包含 Nan 和值的数据集:

import pandas as pd
import numpy as np
data = np.random.randn(6,6)
mask = np.random.choice([1, 0], data.shape, p=[.1, .9]).astype(bool)
data[mask] = np.nan
df = pd.DataFrame(data=data,columns=['2009','2010','2011','2012','2013','2014'])
df

哪个输出

我开始编写以下函数,它为每一行提供从 2011 年到 2009 年的第一个非 NaN 值:

num_row = 0
for row in df.iterrows():
    num_row = num_row+1
    #print("for :" + str(row[1][str(2015)]))
    indicator = float("nan")
    distance_2011 = 0
    year = 2011
    while np.isnan(indicator) and year > 2009:
        year = year - 1
        distance_2011 = distance_2011 - 1
        #print("while : " + str(row[1][str(year)]))
        indicator = row[1][str(year)]
    print("ligne : " + str(num_row) + ", année : " + str(year) + ", valeur : " + str(indicator))
    
)

这输出从 2011 到 2009 的第一个非 NaN 值,它的值和列年份。

但这不会向我的数据集添加新列,也不会帮助我处理从 2011 年到 2014 年的数据

这里有人知道如何解决这个问题吗?我想要每行 2011 年最接近的非 Nan 并将其添加到新列:) 非常感谢!

您可以使用此解决方案

df.loc[:, "new_col"] = df.apply(lambda x: x.loc['2011':].dropna()[0] if x.loc['2011':].dropna().shape[0]>0 else np.nan, axis=1)

希望对您有所帮助!

更新

重新排列您的列:2011 年、2010 年、2012 年、2009 年、2013 年、2014 年:

idx = np.argsort(abs(pd.RangeIndex(df.shape[1]) - df.columns.get_loc('2011')))
df['value'] = df.iloc[:, idx].bfill(axis=1)['2011']
print(df)

# Output
   2009  2010  2011  2012  2013  2014  value
0   1.0   2.0   3.0   4.0   5.0   6.0    3.0
1   1.0   NaN   NaN   4.0   5.0   6.0    4.0
2   1.0   2.0   NaN   NaN   5.0   6.0    2.0
3   1.0   NaN   NaN   NaN   5.0   6.0    1.0
4   NaN   NaN   NaN   NaN   5.0   6.0    5.0

旧答案

IIUC:

df['value'] = df.loc[:, '2011':].bfill(axis=1)['2011']
print(df)

# Output
   2009  2010  2011  2012  2013  2014  value
0   1.0   2.0   3.0   4.0   5.0   6.0    3.0
1   1.0   2.0   NaN   4.0   5.0   6.0    4.0
2   1.0   2.0   NaN   NaN   5.0   6.0    5.0
3   1.0   2.0   NaN   NaN   NaN   6.0    6.0
4   1.0   2.0   NaN   NaN   NaN   NaN    NaN

或更直接:df.bfill(axis=1)['2011']