match语句python3.10中的条件事例(结构模式匹配)



我目前正在开发一些东西,想知道python 3.10中的新match语句是否适合这种用例,在这种用例中我有条件语句。

作为输入,我有一个时间戳和一个包含日期和值的数据帧。目标是在所有行上循环,并根据日期将值添加到相应的bin中。这里,值放在哪个bin中取决于与时间戳相关的日期。时间戳1个月内的日期放在仓1中,2个月内放在仓2中等。

我现在拥有的代码如下:

bins = [0] * 7
for date, value in zip(df.iloc[:,0],df.iloc[:,1]):
match [date,value]:
case [date,value] if date < timestamp + pd.Timedelta(1,'m'):
bins[0] += value
case [date,value] if date > timestamp + pd.Timedelta(1,'m') and date < timestamp + pd.Timedelta(2,'m'):
bins[1] += value
case [date,value] if date > timestamp + pd.Timedelta(2,'m') and date < timestamp + pd.Timedelta(3,'m'):
bins[2] += value
case [date,value] if date > timestamp + pd.Timedelta(3,'m') and date < timestamp + pd.Timedelta(4,'m'):
bins[3] += value
case [date,value] if date > timestamp + pd.Timedelta(4,'m') and date < timestamp + pd.Timedelta(5,'m'):
bins[4] += value
case [date,value] if date > timestamp + pd.Timedelta(5,'m') and date < timestamp + pd.Timedelta(6,'m'):
bins[5] += value

更正:最初我说过这个代码不起作用。事实证明确实如此。然而,我仍然想知道这是否是匹配语句的适当使用。

我认为这不是结构模式匹配的好用,因为没有实际的架构。您正在检查单个对象的,因此如果/elif链是一个更好、更可读、更自然的选择。

我对你的写作方式还有两个问题-

  1. 您不考虑位于bin边缘的值
  2. 您正在检查相同的条件两次,即使您达到了某些签入匹配/情况,您也可以保证之前的条件不匹配-所以如果之前的if date < timestamp + pd.Timedelta(1,'m')检查失败,您不需要执行if date > timestamp + pd.Timedelta(1,'m') and...,您已经知道它并不小。(这是一个平等的边缘案例,但无论如何都应该以某种方式处理(

总而言之,我认为这将是更清洁的解决方案:

for date, value in zip(df.iloc[:,0],df.iloc[:,1]):
if date < timestamp + pd.Timedelta(1,'m'):
bins[0] += value
elif date < timestamp + pd.Timedelta(2,'m'):
bins[1] += value
elif date < timestamp + pd.Timedelta(3,'m'):
bins[2] += value
elif date < timestamp + pd.Timedelta(4,'m'):
bins[3] += value
elif date < timestamp + pd.Timedelta(5,'m'):
bins[4] += value
elif date < timestamp + pd.Timedelta(6,'m'):
bins[5] += value
else:
pass

这真的应该直接用Pandas函数来完成:

import pandas as pd
from datetime import datetime
timestamp = datetime.now()
bins = [pd.Timestamp(year=1970, month=1, day=1)]+[pd.Timestamp(timestamp)+pd.Timedelta(i, 'm') for i in range(6)]+[pd.Timestamp(year=2100, month=1, day=1)] # plus open bin on the right
n_samples = 1000
data = {
'date': [pd.to_datetime(timestamp)+pd.Timedelta(i,'s') for i in range(n_samples)],
'value': list(range(n_samples))
}
df = pd.DataFrame(data)
df['bin'] = pd.cut(df.date, bins, right=False)
df.groupby('bin').value.sum()

最新更新