保留完整的姓氏,在“Pandas”列中获取名字的首字母缩写(如果有的话,还有中间名)

2024-10-01 15:28:55 发布

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

我有一个熊猫数据框,其中一列表示几个网球运动员的姓氏和姓名,如下所示:

   | Player              | 
   |---------------------|
0  | 'Roddick Andy'      |
1  | 'Federer Roger'     |
2  | 'Tsonga Jo Wilfred  |

我想保留完整的姓氏,如果有的话,我想得到名字的首字母和中间名。所以熊猫栏应该如下所示:

   | Player            | 
   |-------------------|
0  | 'Roddick A.'      |
1  | 'Federer R.'      |
2  | 'Tsonga J.W.'     | N.B. J.W. with no space

有人有什么建议吗?谢谢!


Tags: 数据名字姓名playerandy运动员jo姓氏
3条回答

这里有一个str.extractallgroupby的方法:

(df.Player
  .str.extractall('(?P<Surname>\w*)\s(?P<Name>\w*)')
  .groupby(level=0)
  .agg({'Surname':'first',
        'Name': lambda x: x.str[0].add('.').sum()
        })
  .agg(' '.join, axis=1)
)

输出:

0     Roddick A.
1     Federer R.
2    Tsonga J.W.
dtype: object

您可以按如下方式使用df.replace

import pandas as pd 
df = pd.DataFrame({'Player':['Roddick Andy', 'Federer Roger', 'Tsonga Jo Wilfred']})
df = df.replace(r'(?<=\s\w)\w+\s?', value = '.', regex = True)
print(df)

正则表达式:(?<=\s\w)\w+\s?

  • \w+-至少匹配一个单词字符
  • (?<=\s\w)-正向查找(第一步之前必须有一个空格和任何一个单词字符
  • \s?-第一步后面是可选的空白

结果:

        Player
0   Roddick A.
1   Federer R.
2  Tsonga J.W.

编辑:

选项1:

为了交换这两个首字母,我们可以(为了保持使用正则表达式的想法)添加另一个df.replace,以及第二个正则表达式

import pandas as pd 
df = pd.DataFrame({'Player':['Roddick Andy', 'Federer Roger', 'Tsonga Jo Wilfred']})
df = df.replace(r'(?<=\s\w)\w+\s?', value = '.', regex = True)
df = df.replace(r'(.(?=\.)\.)(.(?=\.)\.)?', value = r'\2\1', regex = True)
print(df)

正则表达式:(.(?=\.)\.)(.(?=\.)\.)?

  • (.(?=\.)\.)-捕获组1:匹配后跟(正向前瞻)文字点的任何字符(.),包括匹配点
  • (.(?=\.)\.)?-捕获组2:可选(?)捕获组匹配与捕获组1完全相同的模式

上面的选项不是很动态。但是如果最多有两个首字母,它就可以正常工作。也可以很容易地附加在上面,但是下面的选项会更动态

选项2:

在你继续之前,请允许我提一下我对Python相当陌生,所以我确信我在这里做的事情可以缩短/做得简单得多

这里的想法是split和apend数据帧,然后将除第一列以外的所有列反转为join它们一起返回到数据帧中的单个列中,然后我们可以再次应用df.replace

import pandas as pd
df = pd.DataFrame({'Player':['Roddick Andy', 'Federer Roger', 'Tsonga Jo Wilfred']})
df = df.Player.str.split(None, expand=True).iloc[:, ::-1]
df = df[[list(df.columns)[-1]] + list(df.columns)[:-1]]
df = df[df.columns[0:]].apply(lambda x: ' '.join(x.dropna().astype(str)), axis=1)
df = df.replace(r'(?<=\s\w)\w+\s?', value = '.', regex = True)
print(df)

结果:

        Player
0   Roddick A.
1   Federer R.
2  Tsonga W.J.

假设每个姓氏都是一个单词姓氏:

def shorten_name(name):
    name_as_list = name.split(" ")
    last_name = name_as_list[-1]
    first_names = ".".join([w[0] for w in name_as_list[:-1]]) + "."
    return (last_name, first_names)

这样使用:

last_name, first_names_shortened = shorten_name("Jo Wilfried Tsonga")

相关问题 更多 >

    热门问题