Python/Pandas - 基于多个变量和 if/elif/else 函数创建新变量

Joh*_*man 5 python numpy pandas

我正在尝试创建一个新变量,该变量基于其他几个值的值。我写在这里是因为我尝试在 R 中将其写为嵌套的 ifelse() 语句,但它有太多嵌套的 ifelse,所以它引发了错误,我认为应该有一种更简单的方法在 Python 中解决这个问题。

我有一个数据框(称为 df),看起来大致像这样(尽管实际上它更大,有更多的月/年变量),我已将其作为 pandas DataFrame 读入:

   ID  Sept_2015  Oct_2015  Nov_2015  Dec_2015  Jan_2016  Feb_2016  Mar_2016  \
0   1          0         0         0         0         1         1         1   
1   2          0         0         0         0         0         0         0   
2   3          0         0         0         0         1         1         1   
3   4          0         0         0         0         0         0         0   
4   5          1         1         1         1         1         1         1   

   grad_time  
0        240  
1        218  
2        236  
3          0  
4        206 
Run Code Online (Sandbox Code Playgroud)

我正在尝试创建一个依赖于所有这些变量的值的新变量,但“较早”变量的值需要有先例,因此 if/elif/else 条件会像这样:

if df['Sept_2015'] > 0 & df['grad_time'] <= 236:
    return 236
elif df['Oct_2015'] > 0 & df['grad_time'] <= 237:
    return 237
elif df['Nov_2015'] > 0 & df['grad_time'] <= 238:
    return 238
elif df['Dec_2015'] > 0 & df['grad_time'] <= 239:
    return 239
elif df['Jan_2016'] > 0 & df['grad_time'] <= 240:
    return 240
elif df['Feb_2016'] > 0 & df['grad_time'] <= 241:
    return 241
elif df['Mar_2016'] > 0 & df['grad_time'] <= 242:
    return 242
else:
    return 0
Run Code Online (Sandbox Code Playgroud)

基于此,我希望它返回一个如下所示的新变量:

   trisk
0    240
1      0
2    240
3      0
4    236
Run Code Online (Sandbox Code Playgroud)

我尝试编写这样的函数:

def test_func(df):
    """ Test Function for generating new value"""
    if df['Sept_2015'] > 0 & df['grad_time'] <= 236:
        return 236
    elif df['Oct_2015'] > 0 & df['grad_time'] <= 237:
        return 237
    ...
    else:
        return 0
Run Code Online (Sandbox Code Playgroud)

并将其映射到数据框以创建新变量,如下所示:

new_df = pd.DataFrame(map(test_func, df)) 
Run Code Online (Sandbox Code Playgroud)

但是,当我运行它时,我收到以下 TypeError

 Traceback (most recent call last):

  File "<ipython-input-83-19b45bcda45a>", line 1, in <module>
     new_df = pd.DataFrame(map(new_func, test_df))

  File "<ipython-input-82-a2eb6f9d7a3a>", line 3, in new_func
     if df['Sept_2015'] > 0 & df['grad_time'] <= 236:

TypeError: string indices must be integers, not str
Run Code Online (Sandbox Code Playgroud)

所以我可以看到这里不需要列名称。但我已经尝试了许多其他方法,但无法使其发挥作用。另外,我知道这可能不是编写这个(映射函数)的最佳方法,因此我愿意尝试新的方法来解决生成 trisk 变量的问题。提前致谢,如果我没有提供一些东西,我深表歉意。

piR*_*red 2

设置

df = pd.DataFrame([[0, 0, 0, 0, 1, 1, 1, 240],
                   [0, 0, 0, 0, 0, 0, 0, 218],
                   [0, 0, 0, 0, 1, 1, 1, 236],
                   [0, 0, 0, 0, 0, 0, 0,   0],
                   [1, 1, 1, 1, 1, 1, 1, 206]],
                  pd.Index(range(1, 6), name='ID'),
                  ['Sept_2015', 'Oct_2015', 'Nov_2015', 'Dec_2015',
                   'Jan_2016', 'Feb_2016', 'Mar_2016', 'grad_time'])
Run Code Online (Sandbox Code Playgroud)

我主要使用 numpy 来做这个

a = np.array([236, 237, 238, 239, 240, 241, 242])
b = df.values[:, :-1]
g = df.values[:, -1][:, None] <= a

a[(b & g).argmax(1)] * (b & g).any(1)
Run Code Online (Sandbox Code Playgroud)

将其分配给新列

df['trisk'] = a[(b != 0).argmax(1)] * (b != 0).any(1)

df
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述