使用Pandas(python)中的字典部分映射,返回属性

2024-10-03 02:42:38 发布

您现在位置:Python中文网/ 问答频道 /正文

以下是字典的一个子集:

equiv= {'Urin problem': 'C0/ Urine', 'disorientation': 'C0233407 / Disorientation', 'fatigue': 'C0015672 / Fatigue', 'headache': 'C334 / headache'} 

我要把以下数据映射到这本词典中:

^{pr2}$

输出应如下所示:

drug_id        WD                           Map              Exact_Match

lexapro.1   minor urin problem      C0/ Urine       
lexapro.1   Fatigue                'C0015672 / Fatigue                 1
lexapro.1   disorientation          C0233407 / Disorientation          1
lexapro.1   tiredness           
lexapro.14  dizziness           
lexapro.14  headaches                C334 / headache 

正如你看到的,如果它能找到精确的地图,精确匹配的一栏将填充1,就像疲劳和迷失方向一样。如果项目是部分映射,则映射列将具有相应的值,但精确匹配列没有得到任何值。这是我的代码:

df['Map'] = df["WD"].str.extract('('+'|'.join(list(equiv))+')').map(equiv).fillna(1), 

但是它有以下错误:AttributeError: 'DataFrame' object has no attribute 'map'。但是当我使用这个代码:df['Map'] = df["WD"].map(equiv).fillna(1)时,没有错误。但是,它对部分匹配没有帮助。I also do not know how to fill in the Exact_Match column with 1 when there is exact match.


Tags: mapdfproblemwdc0fatigueequivheadache
3条回答

这有点类似于MaxU的方法(基于replace()),对于这个小例子,速度差不多,比johnchase慢

但您可能希望在更大、更真实的数据帧上进行测试。我只是把它扩展到1500行,这是最快的方法(其次是MaxU,然后是johnchase),但这可能不一定能保存您的实际数据。在

equiv2 = dict( ( k.lower(), v ) for k,v in equiv.items() )
df['Map'] = df.WD.str.lower().replace( equiv2, regex=True )
df.loc[ df.Map == df.WD, 'Map' ] = ''
df['Exact'] = df.WD.isin(equiv).astype(int)

df
Out[166]: 
      drug_id                  WD                        Map  Exact
0   lexapro.1  minor urin problem            minor C0/ Urine      0
1   lexapro.1             Fatigue         C0015672 / Fatigue      0
2   lexapro.1      disorientation  C0233407 / Disorientation      1
3   lexapro.1           tiredness                                 0
4  lexapro.14           dizziness                                 0
5  lexapro.14           headaches           C334 / headaches      0

第三行(df.loc)感觉有点多余或有点老套,但我无法找到一种方法使replace为不匹配项返回NaN或类似的值,所以我只是将“Map”转换为'',如果“WD”==“Map”。不应该拖得太慢,但似乎有更好的方法。。。在

可以使用以下矢量化方法来执行此操作:

mp = pd.DataFrame({'WD':[x.lower() for x in equiv.keys()],
                   'Map':[x for x in equiv.values()]})
df['Map'] = \
    df.WD.str.lower().replace(
        (r'.*\b' + mp.WD + r'[\b\n\r]*.*').tolist(),
        mp.Map.tolist(),
        regex=True
    )
df['Exact_Match'] = df.WD.str.lower().isin(mp.WD.str.lower()).astype(np.uint8)
df.loc[df.WD.eq(df.Map), 'Map'] = ''

演示:

^{pr2}$

我可能会用几个不同的步骤来做这件事,因为我认为这里确实有相当多的事情要做。对于匹配字符串,您可能需要尝试类似python的difflib

第一行是将值设置为1,如果确切的字符串在字典键中,否则返回null。第二行使用difflib获取与键最接近的字符串匹配。您可以查看文档中有关设置返回的相似性阈值的信息。然后,从前面生成的第三行字典返回相似的值。可能有一个更简单的方法来实现这一点,但这是我将如何解决这个问题

from difflib import get_close_matches
import numpy as np

#Set the exact match column if the cell value is in the dictionary keys
df['Exact_Match'] = df['WD'].apply(lambda x: 1 if x in equiv.keys() else np.nan)

#Get the keys that for the dictionary based on close matches
df_keys = df.WD.apply(lambda x: ''.join(get_close_matches(x, equiv.keys(), n=1, cutoff=0.8)))

#return the values of those keys and create a new column for the values
df['MAP'] = [equiv[e] if e else '' for e in df_keys]


    drug_id     WD                  Exact_Match    MAP
0   lexapro.1   minor urin problem  NaN            C0/ Urine
1   lexapro.1   Fatigue             NaN            C0015672 / Fatigue
2   lexapro.1   disorientation      1.0            C0233407 / Disorientation
3   lexapro.1   tiredness           NaN 
4   lexapro.14  dizziness           NaN 
5   lexapro.14  headaches           NaN            C334 / headache

相关问题 更多 >