嗨,我有一个数据集,如下所示:
Format,Message,time
A,ab@1 yl@5 rd@20 pp@40,3
B,bc@1 gn@7 yl@20 ss@25 rd@50, 21
C,cc@1 yl@9 rd@20, 22
我想使用从Messages的yl和rd中提取的数字,然后在其数字(例如yl @ 5 ---> 5)和时间列的数字之间进行数字比较。因此,如果将第1行,第3行与第5行和第20行进行比较,那么如果它小于两个元素,则将赋值为g。如果时间为7,则将分配值y,同样,如果其值为20或更高,则将其分配为r。
所以会像
Format,Message,time,status
A,ab@1 yl@5 rd@20 pp@40,3,g
B,bc@1 gn@7 yl@20 ss@25 rd@50,21,y
C,cc@1 yl@9 rd@20,22,r
答案 0 :(得分:2)
您的问题实际上是很多问题。从“ dataframe”标签看来,您正在使用熊猫来进行此操作。您要查询的正则表达式可能会增加数字“ yl”和“ rd”(如果有的话,我假设它们始终存在)。但是正则表达式通常不进行数学或数值比较,因此仅占第三位。
与'yl'的数值匹配的正则表达式(假定为整数,而不是浮点数):
r'yl@(\d+)'
您可以在单个表达式中提取它们,但前提是它们始终处于相同顺序,或者成为复杂的正则表达式。
要确保仅匹配yl@5
,但不能匹配xyl@5
,则可以对开始(要求空格或行首)和结束(要求空格或行尾)添加一些限制):
r'(^|\s)yl@(\d+)($|\s)'
或者,如果您遇到yl
像a:yl
这样的名称分隔的情况,也可以添加它:
r'(^|\s)([a-z]+:)?l@(\d+)($|\s)'
但是,所有这些只是使用正则表达式语言构建更具体的表达式。 RegexBuddy是我喜欢使用(没有从属关系)的一个非常好的写正则表达式的工具,但是也有相当不错的在线工具,例如https://regex101.com/。
在代码示例中使用,基本上可以完成您建议的操作:
import re
from pandas import DataFrame
df = DataFrame({
'Format': ['A', 'B', 'C'],
'Message': ['ab@1 yl@5 rd@20 pp@40', 'bc@1 gn@7 yl@20 ss@25 rd@50', 'cc@1 yl@9 rd@20'],
'time': [3, 21, 22]
})
def determine_status(row):
def find(tag, message):
match = re.search(rf"{tag}@(\d+)", message)
if match:
return match.group(1)
else:
raise ValueError(f'{tag} not in message.')
yl = int(find('yl', row['Message']))
rd = int(find('rd', row['Message']))
time = int(row['time'])
if time < yl < rd:
return 'g'
if yl <= time < rd:
return 'y'
return 'r'
df['status'] = df.apply(determine_status, axis=1)
print(df)
find
函数使用一个标记和一条消息,并使用正则表达式为消息中的标记生成数值。
determine_status
函数就是这样做的-它期望从DataFrame中获取一行,并将使用Message
和time
列来确定状态并返回状态。
df.apply
然后用于创建新的status
列,并为DataFrame中的每一行填充determine_status
的结果。
您没有指定要使用的Python版本,但是如果它是Python 3.6之前的版本,则会发现f'{tag} not in message.'
之类的表达式不起作用-而是使用诸如'{tag} not in message.'.format(tag=tag)
。
答案 1 :(得分:0)
我认为,这可以通过内置的字符串函数来完成。试试吧!
def f(mess):
p1 = mess.find('yl')
p2 = mess.find('rd')
return int(mess[p1+3:].split(' ')[0]),int(mess[p2+3:].split(' ')[0])
df['vals'] =df['Message'].apply(f)
df['status'] = df.apply(lambda row: 'g' if min(row['vals']) > row.time \
else 'y' if row.vals[1]>row.time \
else 'r', axis=1)
print(df)
输出:
Format Message time vals status
0 A ab@1 yl@5 rd@20 pp@40 3 (5, 20) g
1 B bc@1 yl@20 ss@25 rd@50 21 (20, 50) y
2 C cc@1 yl@9 rd@20 22 (9, 20) r