【问题标题】:Nested If Statement in PandasPandas 中的嵌套 If 语句
【发布时间】:2019-08-20 23:02:35
【问题描述】:

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

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 函数。 提前谢谢你。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    一般情况下,你可以使用np.select实现elif逻辑,详细herehere

    在这种情况下,您可以简洁地使用lookup + notnull().idxmax 来查找每行中的第一个非空值。我添加了一个额外的 all 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
    

    【讨论】:

      【解决方案2】:

      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
      

      【讨论】:

        【解决方案3】:
        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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-06-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多