Python 基于列名和最后一个非NaN值压缩数据帧

Python 基于列名和最后一个非NaN值压缩数据帧,python,pandas,dataframe,Python,Pandas,Dataframe,我有一个熊猫数据框,如下所示: col1 col2 x_1 x_2 x_3 x_4 a b 0.3 0.2 NaN NaN c d 0.4 0.3 0.2 NaN e f 0.2 0.1 NaN NaN v x NaN 0.2 NaN NaN x r NaN NaN NaN NaN 我要做的是为每一行找到最右边的数值,并用两个新列重新构造数据框,第一列包含列名,第二列包含最右边的值,如下所示: col1 col2 col3 col4

我有一个熊猫数据框,如下所示:

col1 col2 x_1 x_2 x_3 x_4 
a    b    0.3 0.2 NaN NaN
c    d    0.4 0.3 0.2 NaN
e    f    0.2 0.1 NaN NaN
v    x    NaN 0.2 NaN NaN
x    r    NaN NaN NaN NaN
我要做的是为每一行找到最右边的数值,并用两个新列重新构造数据框,第一列包含列名,第二列包含最右边的值,如下所示:

col1 col2 col3 col4
a    b    x_2  0.2
c    d    x_3  0.2
e    f    x_2  0.1
v    x    x_2  0.2
x    r    None None

有没有一个简单的方法可以做到这一点,也许可以使用
pandas.apply

使用
系列。最后一个有效的索引将大大帮助您

一个选项是融化数据帧使其变长,而不是按col1和col2进行宽分组,并取最后的非NaN值:

with_value = pd.melt(
    df, 
    id_vars = ['col1', 'col2'], 
    var_name='col3', 
    value_name='col4'
).dropna()
这给了你:

   col1 col2 col3  col4
0     a    b  x_1   0.3
1     c    d  x_1   0.4
2     e    f  x_1   0.2
5     a    b  x_2   0.2
6     c    d  x_2   0.3
7     e    f  x_2   0.1
8     v    x  x_2   0.2
11    c    d  x_3   0.2
          col3  col4
col1 col2           
a    b     x_2   0.2
c    d     x_3   0.2
e    f     x_2   0.1
v    x     x_2   0.2
然后分组并取最后一个值

last_value = with_value.groupby(['col1', 'col2']).last()
这给了你:

   col1 col2 col3  col4
0     a    b  x_1   0.3
1     c    d  x_1   0.4
2     e    f  x_1   0.2
5     a    b  x_2   0.2
6     c    d  x_2   0.3
7     e    f  x_2   0.1
8     v    x  x_2   0.2
11    c    d  x_3   0.2
          col3  col4
col1 col2           
a    b     x_2   0.2
c    d     x_3   0.2
e    f     x_2   0.1
v    x     x_2   0.2
然后重新编制索引并删除索引以获得所需内容,例如:

final = last_value.reindex([df.col1, df.col2]).reset_index()
给你:

  col1 col2 col3  col4
0    a    b  x_2   0.2
1    c    d  x_3   0.2
2    e    f  x_2   0.1
3    v    x  x_2   0.2
4    x    r  NaN   NaN