Pandas数据框-根据多个条件计算创建多个列

时间:2020-07-31 13:57:57

标签: python pandas numpy dataframe data.table

我正在学习python,所以如果我的问题太基本了,请原谅。实际上,我需要根据不同条件在熊猫数据框上创建多个列。我可以在R中使用data.table做到这一点。我在代码下方粘贴了R-

的示例数据
library(data.table)

cr=4
phi=1.85

colA <- sample(1.05:20.00,1000,replace=T)
colB <- sample(1.05:20.00,1000,replace=T)
colC  <- sample(1.05:20.00,1000,replace=T)
SALES <- sample(1.05:20.00,1000,replace=T)
colD <- sample(1.05:20.00,1000,replace=T)
VALUE <- sample(1.05:20.00,1000,replace=T)

df <- as.data.table(data.frame(colA,colB,colC,colD,SALES,VALUE))

df <- df[, c("colB_exp","colC_exp", "Unit_exp","Value_exp") 
         := list (ifelse(!is.na(colA),pmin(colB *  colA,(cr-1)*1/phi^2+cr*SALES * colA),0),
                  ifelse(!is.na(colA),pmin(colC * colA,(cr-1)*1/phi^2+cr*SALES * colD * colA),0),      
                  ifelse(!is.na(colA),SALES * colA,0),
                  ifelse(!is.na(colA),VALUE * colA,0)
         )]        

因此,如您所见,在此示例中我需要创建4列(实际上,还需要创建7个具有不同条件的列,但出于示例目的,我只考虑了4个)

现在,我正在尝试在Python中执行相同的操作,但无法获得如何执行此操作。另外,我不确定我是否以有效的方式执行此操作,因为似乎无法为要创建的每个新列进行过多的编码。 以下是我在Python中尝试的示例数据和代码-

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.uniform(0,100,size=(100, 6)), columns=list(['colA','colB','colC','colD','SALES','VALUE']))

cr=4
phi=1.85

def colB_exp(row):
    return min(df['colB'] *  df['colA'],(cr-1)*1/phi^2+cr* df['SALES'] * df['colA'])


df['colB_exp'] = df.apply(lambda row:colB_exp(row) if df['colA'].notnull().all() else 0,axis = 1)

但是我得到了错误,因为 TypeError:无法对类型为[bool]的dtyped [float64]数组和标量执行'rxor'

当我检查df的数据类型时,所有列都是float64,实际上在我的主数据中就是这种情况。

不确定是什么问题,我该如何解决。

我是否必须为每个列条件创建函数?有更好的方法吗?

谢谢!!

2 个答案:

答案 0 :(得分:1)

您不能使用min直接比较2列。它需要在元素级别应用。 您能检查一下这种故障是否起作用。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.uniform(0,100,size=(100, 6)), columns=list(['colA','colB','colC','colD','SALES','VALUE']))

cr = 4
phi = 1.85

def colB_exp():
    A = df['colB']* df['colA']
    B = (cr-1)*1/phi**2+cr* df['SALES'] * df['colA']
    return [min(a,b) for a,b in zip(A, B)]

df['colB_exp'] = colB_exp()
df['colB_exp'][df['colA'].isna()] = 0
df

答案 1 :(得分:1)

如果避免使用apply,它将更快,您可以使用np.where

>>> df = pd.DataFrame(np.random.uniform(0,100,size=(100, 6)), 
                      columns=list(['colA','colB','colC','colD','SALES','VALUE']))

>>> cr=4
>>> phi=1.85
>>> df['colB_exp'] = np.where(
                              df['colA'].notnull(), 
                              pd.concat([
                                  df['colB'] *  df['colA'],
                                  (cr-1)*1/phi**2+cr* df['SALES'] * df['colA']
                                 ],axis=1).min(1), 0
                        )
>>> df

         colA       colB       colC  ...      SALES      VALUE     colB_exp
0   22.549300  64.278204  31.008298  ...  42.493048  59.603801  1449.428473
1   69.699479  69.173731  98.060696  ...  45.343364  40.046332  4821.373010
2   49.174025  81.000527  62.022084  ...  49.619752  18.370626  3983.121926
3   88.094696  33.193363  59.168448  ...  72.243254   8.378294  2924.159181
4   57.385150  14.326797  92.865076  ...  33.228036  55.651635   822.145427
..        ...        ...        ...  ...        ...        ...          ...
95  94.641142  39.684918  59.073406  ...  66.350751  38.040689  3755.825953
96   7.527524  10.376946  56.894015  ...   8.575608  71.710560    78.112711
97  12.258327  17.919200  97.053017  ...  22.476308  79.233166   219.659423
98  76.264761  60.973407  97.328900  ...  57.116251  29.756769  4650.122372
99  30.687590  77.486464   7.277809  ...  97.560641   4.835084  2377.872852

[100 rows x 7 columns]

您可以进一步查看df.assign,一次添加多个列。