【问题标题】:Extract middle word of letter python提取字母python的中间词
【发布时间】:2018-01-11 07:03:04
【问题描述】:

我有一个名为 df 的熊猫数据框,看起来像这样

Name
------
Mike
Noel
Kim
Anna
Luke
joseph
joe

我如何仅列出名称中间包含单词“n”或“k”的名称。不是第一个字母也不是最后一个字母。结果是

namelist = [Mike, Anna, Luke]

【问题讨论】:

  • 中间是指除第一个或最后一个以外的所有其他字母?因为Mike严格来说没有中间字母
  • df.loc[df.Name.str.contains('\w[nk]\w'), 'Name'].tolist()

标签: python string pandas split


【解决方案1】:

选项 1
你可以这样做,使用str.contains -

df.loc[df.Name.str.contains(r'\w[nk]\w'), 'Name'].tolist()
['Mike', 'Anna', 'Luke']

详情
一、正则表达式——

\w      # any alpha-numeric char
[nk]    # character class; letters "n" and "k"
\w      # any alpha-numeric char

这样可以确保,如果单词以“n”或“k”开头或结尾(不包含在单词中间),它不会被拾取(“n”或“k”必须在两边都有东西)。

一个类似的正则表达式,匹配任何周围的字符(除了字母数字字符)将是 -

r'.[nk].'

或者,如果你想要一个正则表达式匹配一个中间有“n”或“k”的字符串,而结尾是“n”和“k”,使用 -

r'^[^nk].*[nk].*[^nk]$' 

str.contains 调用的输出 -

df.Name.str.contains(r'\w[nk]\w')

0     True
1    False
2    False
3     True
4     True
5    False
6    False
Name: Name, dtype: bool

loc 切片操作的输出 -

df.loc[df.Name.str.contains(r'\w[nk]\w'), 'Name']

0    Mike
3    Anna
4    Luke
Name: Name, dtype: object

现在,拨打pd.Series.tolist 会为您提供您的姓名列表。


选项 2
使用str.findall 的另一个选项 -

df.Name.str.findall(r'^.*\w[nk]\w.*$').str[0].dropna().tolist()
['Mike', 'Anna', 'Luke']

与第一个类似,但有一些不同。

详情
首先,findall 调用的输出 - 匹配列表。正则表达式模式与上面相同,但稍作修改以如果找到中间的模式则捕获整个字符串。

df.Name.str.findall(r'^.*\w[nk]\w.*$')

0    [Mike]
1        []
2        []
3    [Anna]
4    [Luke]
5        []
6        []
Name: Name, dtype: object

从每个列表中获取第一个元素。空列表返回 NaN,随后将其删除 -

df.Name.str.findall(r'.*\w[nk]\w.*').str[0].dropna()

0    Mike
3    Anna
4    Luke
Name: Name, dtype: object

从那里,使用pd.Series.tolist 转换为列表。

【讨论】:

  • 您的代码将选择“nnkk”,但它不应该按照 OP 的要求出现。
  • @rnso 解决了这个问题。
  • 你能说明为什么其他答案(甚至问题)都得到了赞成票,而不是我的答案!
  • @rnso 我通常不会赞成其他答案(除非他们非常好),其他用户也不会。无论选票统计的原因是什么,我都不对此负责。虽然,你的方法效率很低,使用find 和相关的混乱。
  • For 和其他循环比函数方法慢得多,我相信。但在大多数情况下,我认为这并不重要。感谢您的 cmets。
【解决方案2】:

使用boolean indexingstr[1:-1] 删除第一个和最后一个字符,然后通过str.contains 进行检查:

L = df.loc[df['Name'].str[1:-1].str.contains('n|k'), 'Name'].tolist()
print (L)
['Mike', 'Anna', 'Luke']

编辑:如有必要,还排除第一个和最后一个 nk 值:

m = ~df['Name'].str[0].str.lower().isin(['n','k']) &  \
    ~df['Name'].str[-1].str.lower().isin(['n','k']) & \
    df['Name'].str[1:-1].str.contains('n|k')

df = df.loc[m, 'Name'].tolist()
print (df)
['Mike', 'Anna', 'Luke']

【讨论】:

  • 您的代码将选择“nnkk”,但它不应该按照 OP 的要求出现。
  • @rnso - 为它添加了解决方案。
【解决方案3】:

可以在这里使用列表推导。下面的代码还确保不选择像“nnkk”这样的名称(其中 n 和/或 k 都在中间以及一端或两端)。另外,小写和大写都在这里管理:

namelist = df.Name.tolist()              # get all names in a list
outlist = [ n
    for n in namelist
    if n[0].upper() not in ['N','K']     # conditions
       and n[-1].upper() not in ['N','K'] 
       and (n.upper().find("N") >=0 
            or n.upper().find("K") >=0) ]

print(outlist)

输出:

['Mike', 'Anna', 'Luke']

【讨论】:

    猜你喜欢
    • 2022-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多