如何将多个系列合并为一个选择单个非空值?

时间:2017-12-13 12:58:34

标签: python pandas

我在DataFrame(5000000x100)中有三列稀疏非空,如此(非空值是货币代码):

NaN           EUR             EUR
NaN           NaN             NaN
NaN           NaN             NaN
EUR           NaN             NaN
NaN           NaN             NaN
NaN           NaN             NaN
NaN           GBP             NaN
NaN           NaN             NaN
NaN           NaN             NaN
USD           NaN             NaN
NaN           NaN             NaN
NaN           NaN             NaN
NaN           NaN             NaN
NaN           EUR             EUR

我还有一本字典,其转换率为欧元,如下所示:

{'USD':0.8499 , 'EUR': 1 , 'GBP': 1.135}

我希望为每一行创建另一个具有相应转化率的列(我们可以假设一行只有一种货币的实例)EG:

    NaN           EUR             EUR    1
    NaN           NaN             NaN    NaN
    NaN           NaN             NaN    NaN
    EUR           NaN             NaN    1
    NaN           NaN             NaN    NaN
    NaN           NaN             NaN    NaN
    NaN           GBP             NaN    1.135
    NaN           NaN             NaN    NaN
    NaN           NaN             NaN    NaN
    USD           NaN             NaN    0.8499
    NaN           NaN             NaN    NaN
    NaN           NaN             NaN    NaN
    NaN           NaN             NaN    NaN
    NaN           EUR             EUR    1

我可以使用map实现单个列的预期结果。 EG:

res = s.map(conversion_rate_dictionary)

这将给出一个小例子:

s    res
NaN  NaN
EUR  1
GBP  1.135
USD  0.849
NaN  NaN 

我很难直接或通过在每个列上组合地图的结果来获得所需的结果。感谢您的任何建议

1 个答案:

答案 0 :(得分:1)

使用replaceffill一起转发NaN,然后按DataFrame.iloc选择最后一栏:

d = {'USD':0.8499 , 'EUR': 1 , 'GBP': 1.135}
df['new'] = df.replace(d).ffill(axis=1).iloc[:, -1]
print (df)
      a    b    c     new
0   NaN  EUR  EUR  1.0000
1   NaN  NaN  NaN     NaN
2   NaN  NaN  NaN     NaN
3   EUR  NaN  NaN  1.0000
4   NaN  NaN  NaN     NaN
5   NaN  NaN  NaN     NaN
6   NaN  GBP  NaN  1.1350
7   NaN  NaN  NaN     NaN
8   NaN  NaN  NaN     NaN
9   USD  NaN  NaN  0.8499
10  NaN  NaN  NaN     NaN
11  NaN  NaN  NaN     NaN
12  NaN  NaN  NaN     NaN
13  NaN  EUR  EUR  1.0000

详情:

print (df.replace(d).ffill(axis=1))
         a       b       c
0      NaN  1.0000  1.0000
1      NaN     NaN     NaN
2      NaN     NaN     NaN
3   1.0000  1.0000  1.0000
4      NaN     NaN     NaN
5      NaN     NaN     NaN
6      NaN  1.1350  1.1350
7      NaN     NaN     NaN
8      NaN     NaN     NaN
9   0.8499  0.8499  0.8499
10     NaN     NaN     NaN
11     NaN     NaN     NaN
12     NaN     NaN     NaN
13     NaN  1.0000  1.0000

大型DataFrame中的Numpy解决方案更快:

d = {'USD':0.8499 , 'EUR': 1 , 'GBP': 1.135}

a = df.replace(d).values
m = ~np.isnan(a)
b = a[np.arange(m.shape[0]), m.shape[1]-m[:,::-1].argmax(1)-1]
print (b)
[ 1.         nan     nan  1.         nan     nan  1.135      nan     nan
  0.8499     nan     nan     nan  1.    ]

df['new'] = b
print (df)
      a    b    c     new
0   NaN  EUR  EUR  1.0000
1   NaN  NaN  NaN     NaN
2   NaN  NaN  NaN     NaN
3   EUR  NaN  NaN  1.0000
4   NaN  NaN  NaN     NaN
5   NaN  NaN  NaN     NaN
6   NaN  GBP  NaN  1.1350
7   NaN  NaN  NaN     NaN
8   NaN  NaN  NaN     NaN
9   USD  NaN  NaN  0.8499
10  NaN  NaN  NaN     NaN
11  NaN  NaN  NaN     NaN
12  NaN  NaN  NaN     NaN
13  NaN  EUR  EUR  1.0000