【问题标题】:including word boundary in string modification to be more specific在字符串修改中包括单词边界更具体
【发布时间】:2019-12-07 07:50:14
【问题描述】:

背景

以下是对modification of skipping empty list and continuing with function的小改动

import pandas as pd
Names =    [list(['ann']),
               list([]),
               list(['elisabeth', 'lis']),
               list(['his','he']),
               list([])]
df = pd.DataFrame({'Text' : ['ann had an anniversery today', 
                                       'nothing here', 
                                       'I like elisabeth and lis 5 lists ',
                                        'one day he and his cheated',
                                        'same here'
                            ], 

                          'P_ID': [1,2,3, 4,5], 
                          'P_Name' : Names

                         })

#rearrange columns
df = df[['Text', 'P_ID', 'P_Name']]
df
                  Text                P_ID  P_Name
0   ann had an anniversery today        1   [ann]
1   nothing here                        2   []
2   I like elisabeth and lis 5 lists    3   [elisabeth, lis]
3   one day he and his cheated          4   [his, he]
4   same here                           5   []

下面的代码有效

m = df['P_Name'].str.len().ne(0)
df.loc[m, 'New'] = df.loc[m, 'Text'].replace(df.loc[m].P_Name,'**BLOCK**',regex=True) 

然后执行以下操作

1) 使用P_Name 中的名称通过放置**BLOCK** 来阻止Text 列中的相应文本

2) 产生一个新列New

如下图所示

   Text  P_ID P_Name  New
0                     **BLOCK** had an **BLOCK**iversery today
1                     NaN
2                     I like **BLOCK** and **BLOCK** 5 **BLOCK**ts
3                     one day **BLOCK** and **BLOCK** c**BLOCK**ated
4                     NaN

问题

但是,这段代码运行起来有点“太好了”。

使用来自P_Name['his','he'] 来阻止Text

示例:one day he and his cheated 变为 one day **BLOCK** and **BLOCK** c**BLOCK**ated

期望:one day he and his cheated 变为 one day **BLOCK** and **BLOCK** cheated

在这个例子中,我希望cheated 保持cheated 而不是c**BLOCK**ated

期望的输出

    Text P_ID P_Name  New
0                     **BLOCK** had an anniversery today
1                     NaN
2                     I like **BLOCK** and **BLOCK**5 lists
3                     one day **BLOCK** and **BLOCK** cheated
4                     NaN

问题

如何实现我想要的输出?

【问题讨论】:

    标签: python-3.x string pandas text replace


    【解决方案1】:

    有时候for loop 是个好习惯

    df['New']=[pd.Series(x).replace(dict.fromkeys(y,'**BLOCK**') ).str.cat(sep=' ')for x , y in zip(df.Text.str.split(),df.P_Name)]
    df.New.where(df.P_Name.astype(bool),inplace=True)
    df
                                    Text  ...                                  New
    0       ann had an anniversery today  ...     **BLOCK** had an anniversery today
    1                       nothing here  ...                                  NaN
    2  I like elisabeth and lis 5 lists   ...   I like **BLOCK** and **BLOCK** 5 lists
    3         one day he and his cheated  ...  one day **BLOCK** and **BLOCK** cheated
    4                          same here  ...                                  NaN
    [5 rows x 4 columns]
    

    【讨论】:

      【解决方案2】:

      您需要为df.loc[m].P_Name列表中的每个字符串添加单词边界,如下所示:

      s = df.loc[m].P_Name.map(lambda x: [r'\b'+item+r'\b' for item in x])
      
      Out[71]:
      0                   [\bann\b]
      2    [\belisabeth\b, \blis\b]
      3           [\bhis\b, \bhe\b]
      Name: P_Name, dtype: object
      
      df.loc[m, 'Text'].replace(s, '**BLOCK**',regex=True)
      
      Out[72]:
      0       **BLOCK** had an anniversery today
      2    I like **BLOCK** and **BLOCK** 5 lists
      3    one day **BLOCK** and **BLOCK** cheated
      Name: Text, dtype: object
      

      【讨论】:

        猜你喜欢
        • 2012-04-29
        • 2016-09-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-03
        • 2016-05-30
        • 1970-01-01
        • 2021-09-07
        相关资源
        最近更新 更多