- 我的问题是如何根据另一列中的内容在新列中添加一些值
- 在我的特定情况下,我有一个数据帧,它有一个名为
'Flop'
的列,它有3个不同类别的字符串值 - 我可以用regex找到这些"类别",基于每个类别,我想用每个类别的名称创建另一个名为
'Suitedness'
的列
我的df的一个例子是:
import pandas as pd
df = pd.DataFrame()
df['Flop']=['As 5d 7c','As 9s 3s','8c 7d 5s','8d, As, Js','Qs Ts 8d','7s 2s 2d']
初始数据帧
Flop
As 5d 7c
As 9s 3s
8c 7d 5s
8d, As, Js
Qs Ts 8d
7s 2s 2d
我用这种方式解决问题:
Monotone = df[df['Flop'].str.contains('(wss){2}ws',na=False)]
Monotone['Suitedness']= 'Monotone'
Rainbow = df[df['Flop'].str.contains('(wcs.*)+|(w.swc.*)+|(w[s,d,c]sw[s,d,c]swc)+',na=False)]
Rainbow['Suitedness']= 'Rainbow'
DoubleSuited = df[df['Flop'].str.contains('((wss){2}w[d,c])+|(wssw[d,c]sws)+|(w[d,c]swssws)+',na=False)]
DoubleSuited['Suitedness']= 'Double Suited'
df2 = pd.concat([Monotone,Rainbow,DoubleSuited])
df2 = df2.sort_index()
- 这段代码创建了3个不同的数据帧,并将它们连接起来。
- 此解决方案有效,但不美观
- 我正在寻找一种更清洁的解决方案
- 同样,我的regex语法也有点混乱。
- 这三个类别是基于字母"s"、"1"、"2"或"3">
- 我还想要一些关于更好的regex语法的提示
最终数据帧
Flop Suitedness
As 5d 7c Rainbow
As 9s 3s Monotone
8c 7d 5s Rainbow
Qs Ts 8d Double Suited
7s 2s 2d Double Suited
- 使用示例数据
- 此解决方案不会更改正在使用的正则表达式,它只简化了
'Flop'
中每个字符串的'Suitedness'
的设置- 请参阅SO:Regex标记Wiki,了解如何提高正则表达式的效率
- 访问regex101测试正则表达式
- 创建一个包含正则表达式和相关短语的词典
- 使用熊猫。Series.apply具有列表理解,它返回一个具有正确
Suitedness
的列表,如果与re.match
不匹配,则返回一个空列表。- 期望只有一场比赛,或者没有比赛,熊猫。Series.explose用于返回索引0处的值。
- 列表索引选择不适用于列表为空的情况(例如
[][0]
(,因为它会导致IndexError
- 列表索引选择不适用于列表为空的情况(例如
- 期望只有一场比赛,或者没有比赛,熊猫。Series.explose用于返回索引0处的值。
- 如果不关心
NaN
值,请使用df = df.dropna()
删除这些行
import pandas as pd
import re
# create a dict of mappings
mapping = {'(wss){2}ws': 'Monotone',
'(wcs.*)+|(w.swc.*)+|(w[s,d,c]sw[s,d,c]swc)+': 'Rainbow',
'((wss){2}w[d,c])+|(wssw[d,c]sws)+|(w[d,c]swssws)+': 'Double Suited'}
# apply a list comprehension
df['Suitedness'] = df.Flop.apply(lambda x: [v for k, v in mapping.items() if re.match(k, x)]).explode()
# display(df)
Flop Suitedness
As 5d 7c Rainbow
As 9s 3s Monotone
8c 7d 5s Rainbow
8d, As, Js NaN
Qs Ts 8d Double Suited
7s 2s 2d Double Suited