Python 使用Pandas中的字典从两列创建新列
我想基于组和阈值创建一个列,用于为分组列的每个组从另一列断开 数据帧如下所示:Python 使用Pandas中的字典从两列创建新列,python,pandas,dictionary,pandas-apply,Python,Pandas,Dictionary,Pandas Apply,我想基于组和阈值创建一个列,用于为分组列的每个组从另一列断开 数据帧如下所示: df_in -> unique_id myvalue identif 0 CTA15 19.0 TOP 1 CTA15 22.0 TOP 2 CTA15 28.0 TOP 3 CTA15 18.0 TOP 4 CTA15 22.4 TOP
df_in ->
unique_id myvalue identif
0 CTA15 19.0 TOP
1 CTA15 22.0 TOP
2 CTA15 28.0 TOP
3 CTA15 18.0 TOP
4 CTA15 22.4 TOP
5 AC007 2.0 TOP
6 AC007 2.3 SDME
7 AC007 2.0 SDME
8 AC007 5.0 SDME
9 AC007 3.0 SDME
10 AC007 31.4 SDME
11 AC007 4.4 SDME
12 CGT6 9.7 BTME
13 CGT6 44.5 BTME
14 TVF5 6.7 BTME
15 TVF5 9.1 BTME
16 TVF5 10.0 BTME
17 BGD1 1.0 BTME
18 BGD1 1.6 NON
19 GHB 51.0 NON
20 GHB 54.0 NON
21 GHB 4.7 NON
因此,我根据“identif”列的每组创建了一个字典,如下所示:
md = {'TOP': 22, 'SDME': 10, 'BTME': 20, 'NON':20}
因此,我的目标是根据以下条件创建一个新列,称为“chk”:
如果“identif”列与字典“md”中的键匹配,并且该键的值大于“myvalue”列中的相应值,则
我将有1,否则为0
但是,我正试图找到一种使用map/groupby/apply创建新输出数据帧的好方法。我现在做的是一种非常低效的方法(在百万行的实际数据上花费了相当多的时间)
使用如下函数:
def myfilter(df, idCol, valCol, mydict):
for index,row in df.iterrows():
for key, value in mydict.items():
if row[idCol] == key and row[valCol] >= value:
df['chk'] = 1
elif row[idCol] == key and row[valCol] < value:
df['chk'] = 0
return df
因此,我的输出将如下所示:
df_out ->
unique_id myvalue identif chk
0 CTA15 19.0 TOP 0
1 CTA15 22.0 TOP 1
2 CTA15 28.0 TOP 1
3 CTA15 18.0 TOP 0
4 CTA15 22.4 TOP 1
5 AC007 2.0 TOP 0
6 AC007 2.3 SDME 0
7 AC007 2.0 SDME 0
8 AC007 5.0 SDME 0
9 AC007 3.0 SDME 0
10 AC007 31.4 SDME 1
11 AC007 4.4 SDME 0
12 CGT6 9.7 BTME 0
13 CGT6 44.5 BTME 1
14 TVF5 6.7 BTME 0
15 TVF5 9.1 BTME 0
16 TVF5 10.0 BTME 0
17 BGD1 1.0 BTME 0
18 BGD1 1.6 NON 0
19 GHB 51.0 NON 1
20 GHB 54.0 NON 1
21 GHB 4.7 NON 0
这是可行的,但效率极低,需要一种更好的方法来实现。首先,对于数据帧中的每一行,您要遍历字典中的每个元素,总共遍历数据集四次。您可以将函数更改为遍历它一次。这将加速您原来的功能。尝试以下方法:
def myfilter(df, idCol, valCol, mydict):
for index,row in df.iterrows():
value = mydict.get(row[idCol])
if row[valCol] >= value:
df['chk'] = 1
else:
df['chk'] = 0
return df
首先,对数据帧中的每一行遍历字典中的每个元素,总共遍历数据集四次。您可以将函数更改为遍历它一次。这将加速您原来的功能。尝试以下方法:
def myfilter(df, idCol, valCol, mydict):
for index,row in df.iterrows():
value = mydict.get(row[idCol])
if row[valCol] >= value:
df['chk'] = 1
else:
df['chk'] = 0
return df
这应该更快:
def func(identif, value):
if identif in md:
if value >= md[identif]:
return 1.0
else:
return 0.0
else:
return np.NaN
df['chk'] = df.apply(lambda row: func(row['identif'], row['myvalue']), axis=1)
这个小例子的时机:
CPU times: user 1.64 ms, sys: 73 µs, total: 1.71 ms
Wall time: 1.66 ms
您的版本定时:
CPU times: user 8.6 ms, sys: 1.92 ms, total: 10.5 ms
Wall time: 8.79 ms
虽然在这样一个小的例子中,它不是决定性的。这应该更快:
def func(identif, value):
if identif in md:
if value >= md[identif]:
return 1.0
else:
return 0.0
else:
return np.NaN
df['chk'] = df.apply(lambda row: func(row['identif'], row['myvalue']), axis=1)
这个小例子的时机:
CPU times: user 1.64 ms, sys: 73 µs, total: 1.71 ms
Wall time: 1.66 ms
您的版本定时:
CPU times: user 8.6 ms, sys: 1.92 ms, total: 10.5 ms
Wall time: 8.79 ms
虽然在这样一个小的例子中,它不是决定性的。您想要的是将一个函数应用于所有df。你有没有检查过你想要的是把一个函数应用到你所有的df上。您是否已检查此项不起作用,因为它无法确保idCol与字典键以及相应的。我需要满足这两个条件。您的代码确保只满足myvalue标准。此代码根据
idCol
从词典中选取值。你不必遍历整本字典就能做到这一点。字典对该键进行散列,并返回与该键关联的值(如果存在)。如果不存在键,则返回值None
。因此,检查idCol
是否匹配是多余的。这只是为了在不使用apply的情况下提高性能。尽管,apply可能是您想要的。这不起作用,因为它无法确保idCol与字典键以及相应的。我需要满足这两个条件。您的代码确保只满足myvalue标准。此代码根据idCol
从词典中选取值。你不必遍历整本字典就能做到这一点。字典对该键进行散列,并返回与该键关联的值(如果存在)。如果不存在键,则返回值None
。因此,检查idCol
是否匹配是多余的。这只是为了在不使用apply的情况下提高性能。虽然,申请可能是你想要的。谢谢。我觉得这样好多了。如何修改函数并将dict作为参数应用,例如:def func(identif,value,md):??在这种情况下,apply函数将如何更改。我们只需将其作为参数传递,如sodf['chk']=df.apply(lambda行:func(行['identif',行['myvalue',md],轴=1)
Perfect!!工作起来很有魅力!谢谢,谢谢。我觉得这样好多了。如何修改函数并将dict作为参数应用,例如:def func(identif,value,md):??在这种情况下,apply函数将如何更改。我们只需将其作为参数传递,如sodf['chk']=df.apply(lambda行:func(行['identif',行['myvalue',md],轴=1)
Perfect!!工作起来很有魅力!谢谢