如何在 pandas numpy 中快速应用函数时在 pandas numpy 中使用 if else
How to use if else in pandas numpy when apply function in all the rows fast
我有一个数据框 df_ia:
dod1 dod2
0 0 0
1 200806 0
2 200806 0
3 200806 0
4 200806 0
5 200806 0
6 200806 0
7 200806 0
和一个用于应用于每一行的函数:
def life_status(dod1, dod2):
if dod1.any() == 0:
ls1 = '1'
else:
ls1 = '0'
if dod2.any() == 0:
ls2 = '1'
else:
ls2 = '0'
lifestatus = ls1 + ls2
return lifestatus
df_ia['lifestatus'] = life_status(df_ia['dod1'].values,df_ia['dod2'].values)
但是我发现,我不能直接使用:
if dod1.any() to add condition
所以我尝试了类似的东西,
if np.any(dod1==0):
ls1='1'
但是还是不行。
输出应如下所示:
dod1 dod2 lifestatus
0 0 0 11
1 200806 0 01
2 200806 0 01
3 200806 0 01
4 200806 0 01
5 200806 0 01
6 200806 0 01
7 200806 0 01
8 200806 0 01
9 200806 0 01
我可以用这段代码来实现,
def life_status(row):
if row['dod1'] == 0:
ls1 = '1'
else:
ls1 = '0'
if row['dod2'] == 0:
ls2 = '1'
else:
ls2 = '0'
lifestatus = ls1 + ls2
return lifestatus
df['lifestatus'] = df.apply(lambda row: life_status(row), axis=1)
但它非常慢,这就是为什么我 post 这个问题。
解决方案
根据您在评论部分的解释,您之前共享的函数逻辑错误,误导了我之前的解决方案。您需要为每一行评估 int(dod1[i] == 0) + int(dod2[i] == 0)
和 return 一个系列或 numpy.ndarray.
import numpy as np
import pandas as pd
df = pd.DataFrame({
'dod1': [0] + [200806 for _ in range(7)],
'dod2': [0 for _ in range(8)],
})
def life_status(dod1: np.ndarray, dod2: np.ndarray):
return (dod1 == 0).astype(int).astype(str) + (dod2 == 0).astype(int).astype(str)
life_status(df['dod1'].values, df['dod2'].values)
## Output:
# I will update this later. But the function should work as expected.
或者,等效地,直接在数据帧上使用它。
(df.dod1 == 0).astype(int).astype(str) + (df.dod2 == 0).astype(int).astype(str)
给 reader
的注释
如果你想让它更通用,比如当 (dod1 == 0)
为 True 时,赋值 4
,当它为 False 时,赋值 5
,你可以这样做如下。
# schema:
# - condition: dod1 == 0 --> True: 4, False: 5
# - condition: dod1 == 0 --> True: 7, False: 8
cond1, cond2 = (df.dod1 == 0), (df.dod2 == 0)
((cond1 * 4 + ~cond1 * 5).astype(str) + (cond2 * 7 + ~cond2 * 8).astype(str)).tolist()
## Output
# ['47', '57', '57', '57', '57', '57', '57', '57']
您可以进一步改进它并允许任何值(str
、int
、float
)根据它是真还是假来替换。
(df.dod1 == 0).astype(str).replace({'True': '4', 'False': '5'}) + \
(df.dod2 == 0).astype(str).replace({'True': '7', 'False': '8'})
## Output
# ['47', '57', '57', '57', '57', '57', '57', '57']
我有一个数据框 df_ia:
dod1 dod2
0 0 0
1 200806 0
2 200806 0
3 200806 0
4 200806 0
5 200806 0
6 200806 0
7 200806 0
和一个用于应用于每一行的函数:
def life_status(dod1, dod2):
if dod1.any() == 0:
ls1 = '1'
else:
ls1 = '0'
if dod2.any() == 0:
ls2 = '1'
else:
ls2 = '0'
lifestatus = ls1 + ls2
return lifestatus
df_ia['lifestatus'] = life_status(df_ia['dod1'].values,df_ia['dod2'].values)
但是我发现,我不能直接使用:
if dod1.any() to add condition
所以我尝试了类似的东西,
if np.any(dod1==0):
ls1='1'
但是还是不行。
输出应如下所示:
dod1 dod2 lifestatus
0 0 0 11
1 200806 0 01
2 200806 0 01
3 200806 0 01
4 200806 0 01
5 200806 0 01
6 200806 0 01
7 200806 0 01
8 200806 0 01
9 200806 0 01
我可以用这段代码来实现,
def life_status(row):
if row['dod1'] == 0:
ls1 = '1'
else:
ls1 = '0'
if row['dod2'] == 0:
ls2 = '1'
else:
ls2 = '0'
lifestatus = ls1 + ls2
return lifestatus
df['lifestatus'] = df.apply(lambda row: life_status(row), axis=1)
但它非常慢,这就是为什么我 post 这个问题。
解决方案
根据您在评论部分的解释,您之前共享的函数逻辑错误,误导了我之前的解决方案。您需要为每一行评估 int(dod1[i] == 0) + int(dod2[i] == 0)
和 return 一个系列或 numpy.ndarray.
import numpy as np
import pandas as pd
df = pd.DataFrame({
'dod1': [0] + [200806 for _ in range(7)],
'dod2': [0 for _ in range(8)],
})
def life_status(dod1: np.ndarray, dod2: np.ndarray):
return (dod1 == 0).astype(int).astype(str) + (dod2 == 0).astype(int).astype(str)
life_status(df['dod1'].values, df['dod2'].values)
## Output:
# I will update this later. But the function should work as expected.
或者,等效地,直接在数据帧上使用它。
(df.dod1 == 0).astype(int).astype(str) + (df.dod2 == 0).astype(int).astype(str)
给 reader
的注释如果你想让它更通用,比如当 (dod1 == 0)
为 True 时,赋值 4
,当它为 False 时,赋值 5
,你可以这样做如下。
# schema:
# - condition: dod1 == 0 --> True: 4, False: 5
# - condition: dod1 == 0 --> True: 7, False: 8
cond1, cond2 = (df.dod1 == 0), (df.dod2 == 0)
((cond1 * 4 + ~cond1 * 5).astype(str) + (cond2 * 7 + ~cond2 * 8).astype(str)).tolist()
## Output
# ['47', '57', '57', '57', '57', '57', '57', '57']
您可以进一步改进它并允许任何值(str
、int
、float
)根据它是真还是假来替换。
(df.dod1 == 0).astype(str).replace({'True': '4', 'False': '5'}) + \
(df.dod2 == 0).astype(str).replace({'True': '7', 'False': '8'})
## Output
# ['47', '57', '57', '57', '57', '57', '57', '57']