我有一个熊猫数据框,其中有一列表示几位网球运动员的姓氏和名字,如下所示:
| 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
有人有什么建议吗?感谢
以下是一种使用str.extractall
和groupby
的方法:
(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'(?<=sw)w+s?', value = '.', regex = True)
print(df)
正则表达式:(?<=sw)w+s?
w+
-至少匹配一个单词字符(?<=sw)
-正向查找(第一步前面必须有一个空格和任何一个单词字符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'(?<=sw)w+s?', value = '.', regex = True)
df = df.replace(r'(.(?=.).)(.(?=.).)?', value = r'21', regex = True)
print(df)
正则表达式:(.(?=.).)(.(?=.).)?
(.(?=.).)
-捕获组1:匹配后面跟着(正向前瞻(文字点的任何字符(.
(,包括匹配点(.(?=.).)?
-捕获组2:可选(?
(捕获组,与捕获组1完全匹配
以上内容不是很动态。但当最多有两个首字母缩写时,它会很好地工作。也可以很容易地附加在上面,但是下面的选项会更动态。
选项2:
在你继续之前,我可以说我对Python
还很陌生,所以我相信我在这里所做的事情可以缩短/做得简单得多。
这里的想法是split
并结束数据帧,然后将除第一列外的所有列反转为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'(?<=sw)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")