在熊猫中嵌套if语句

时间:2019-08-20 14:17:52

标签: python pandas

这是金融工具标识符的数据框

import pandas as pd
import numpy as np

df = pd.DataFrame([["ISIN1", "CUSIP1", "SEDOL1"], 
                  ["ISIN2", "CUSIP2", "SEDOL2"], 
                  ["ISIN3", "CUSIP3", "SEDOL3"], 
                  ["ISIN4", "CUSIP4", "SEDOL4"]], 
                  columns=["ISIN", "CUSIP", "SEDOL"])

df

    ISIN    CUSIP   SEDOL
0   ISIN1   CUSIP1  SEDOL1
1   ISIN2   CUSIP2  SEDOL2
2   ISIN3   CUSIP3  SEDOL3
3   ISIN4   CUSIP4  SEDOL4

想象一下,缺少几个条目

df.iloc[(1,1)]  = np.nan
df.iloc[(1,2)]  = np.nan
df.iloc[(2,0)]  = np.nan
df.iloc[(3,0)]  = np.nan
df.iloc[(3,1)]  = np.nan
df

    ISIN    CUSIP   SEDOL
0   ISIN1   CUSIP1  SEDOL3
1   ISIN2   NaN     NaN
2   NaN     CUSIP3  SEDOL3
3   NaN     NaN     SEDOL4

在列ID中,我想基于此层次结构捕获单个变量:如果缺少ISIN,则要填充CUSIP。如果还缺少CUSIP,我想填充SEDOL。

我尝试了这个嵌套的if语句:

def identifier(row):

    if ~pd.isnull(row['ISIN']):
        return row['ISIN']
    elif pd.isnull(row['ISIN']) & ~pd.isnull(row['CUSIP']):
        return row['CUSIP']
    elif pd.isnull(row['ISIN']) & pd.isnull(row['CUSIP']) & ~pd.isnull(row['SEDOL']):
        return row['SEDOL']

df['ID'] = df[['SEDOL', 'CUSIP', 'ISIN']].apply(identifier, axis=1)

最近2个条目在ID列中返回错误的输出。

    ISIN    CUSIP   SEDOL   ID
0   ISIN1   CUSIP1  SEDOL1  ISIN1
1   ISIN2   NaN     NaN     ISIN2
2   NaN     CUSIP3  SEDOL3  NaN
3   NaN     NaN     SEDOL4  NaN

我的预期输出是这样:

    ISIN    CUSIP   SEDOL   ID
0   ISIN1   CUSIP1  SEDOL1  ISIN1
1   ISIN2   NaN     NaN     ISIN2
2   NaN     CUSIP3  SEDOL3  CUSIP3
3   NaN     NaN     SEDOL4  SEDOL4

希望我已经很好地解释了。 请注意,“ ISIN”是一个字符串。我的代码中没有使用.isin函数。 预先谢谢你。

3 个答案:

答案 0 :(得分:3)

通常,您可以使用elif(详细介绍herehere)来实现np.select逻辑。

在这种情况下,您可以使用lookup + notnull().idxmax简洁地执行此操作,以查找每行中的第一个非空值。我添加了一个额外的NaN行,以说明该如何处理。

df['ID'] = df.lookup(df.index, df.notnull().idxmax(1))

#    ISIN   CUSIP   SEDOL      ID
#0  ISIN1  CUSIP1  SEDOL1   ISIN1
#1  ISIN2     NaN     NaN   ISIN2
#2    NaN  CUSIP3  SEDOL3  CUSIP3
#3    NaN     NaN  SEDOL4  SEDOL4
#4    NaN     NaN     NaN     NaN

为解释您最初遇到的问题,将~pd.isnull一起使用。

df['ISIN'].apply(lambda x: ~pd.isnull(x))
0   -1
1   -1
2   -2
3   -2
4   -2
Name: ISIN, dtype: int64

这些不是0,因此它们的取值为True,这意味着您在'ISIN'列中的每一行。您应该使用pd.notnullnot pd.isnull也可以)而不是~pd.isnull

df['ISIN'].apply(lambda x: pd.notnull(x))
0     True
1     True
2    False
3    False
4    False
Name: ISIN, dtype: bool

答案 1 :(得分:1)

IIUC使用bfill

df['ID']=df.bfill(1).iloc[:,0]
df
Out[346]: 
    ISIN   CUSIP   SEDOL      ID
0  ISIN1  CUSIP1  SEDOL3   ISIN1
1  ISIN2     NaN     NaN   ISIN2
2    NaN  CUSIP3  SEDOL3  CUSIP3
3    NaN     NaN  SEDOL4  SEDOL4

答案 2 :(得分:1)

from functools import reduce
df.loc[:, 'ID'] = reduce(lambda c1, c2: c1.combine_first(c2), [df[c] for c in df])
Out[68]: 
    ISIN   CUSIP   SEDOL      ID
0  ISIN1  CUSIP1  SEDOL1   ISIN1
1  ISIN2     NaN     NaN   ISIN2
2    NaN  CUSIP3  SEDOL3  CUSIP3
3    NaN     NaN  SEDOL4  SEDOL4
相关问题