我正在尝试查看是否有办法使用Pandas进行以下计算:
我有一个表格,其中包含事件编号,后跟它们各自的开始和结束日期时间。
Event Number Start End
1 6/1/2020 13:00 6/1/2020 13:30
2 6/1/2020 17:45 6/1/2020 19:15
3 6/4/2020 8:00 6/4/2020 9:10
4 6/7/2020 11:00 6/7/2020 11:50
另外,我还有另一个表,其中包含每个传感器的原始时间索引数据
Datetime Sensor 1 Sensor 2 Sensor 3
6/1/2020 0:00 80 4 0
6/1/2020 0:01 80 5 0
6/1/2020 0:02 69 9 1
6/1/2020 0:03 72 8 0
6/1/2020 0:04 60 9 0
6/1/2020 0:05 76 3 0
6/1/2020 0:06 62 8 1
6/1/2020 0:07 80 8 0
6/1/2020 0:08 64 7 1
有没有办法让我运行原始表并根据 START 和 END 时间戳裁剪这个表?
我正在尝试最终表看起来像什么,包括
- 打开
- 关闭
- 最小值
- 麦克斯
- 意味 着
这些日期之间的所有传感器。
我尝试使用for循环没有太多运气,但它需要很长(+3M行原始数据(。
有没有办法对熊猫做到这一点?
提前感谢大家
编辑 1:添加了我想到的输出作为澄清:
Event Type Sensor 1 Sensor 2 Sensor 3
1 Open 60 5 1
1 Close 69 8 0
1 Max 78 8 1
1 Min 59 4 0
1 Mean 69 8 0.333
2 Open 77 4 0
2 Close 73 6 1
2 Max 77 6 1
2 Min 68 4 0
2 Mean 74 6 0.667
3 Open 63 4 1
3 Close 71 7 1
3 Max 70 8 1
3 Min 63 3 0
3 Mean 65 4 1
可以使用pd.between
获取所需的传感器值,然后创建多索引数据帧以改进所获取数据的显示。您将在此处找到有用的信息:如何检查熊猫中两个日期时间之间的位置日期时间和构造 3D-pandas-dataframe。你可以尝试这样的事情:
import pandas as pd
import numpy as np
import io
from statistics import mean
s_e = """Event Number start end
1 6/1/2020 0:00 6/1/2020 0:02
2 6/1/2020 0:05 6/1/2020 0:08"""
s_s = """ Datetime Sensor 1 Sensor 2 Sensor 3
6/1/2020 0:00 80 4 0
6/1/2020 0:01 80 5 0
6/1/2020 0:02 69 9 1
6/1/2020 0:03 72 8 0
6/1/2020 0:04 60 9 0
6/1/2020 0:05 76 3 0
6/1/2020 0:06 62 8 1
6/1/2020 0:07 80 8 0
6/1/2020 0:08 64 7 1"""
events = pd.read_csv(io.StringIO(s_e), sep='ss+', parse_dates=[1,2], engine='python')
sensors = pd.read_csv(io.StringIO(s_s), sep='ss+', parse_dates=[0], engine='python')
#We create a dataframe with all values of ['Values','Open','Close','Min' ,'Max', 'Mean'] of each sensor
dfEveSen=pd.DataFrame()
pd.set_option('display.max_columns', None)
for sensor in sensors.columns[1:]:
#we get the sensor values between start and end of each event
dfEveSen[sensor+'values']=[list(sensors[sensor][sensors.Datetime.between(start, end)].agg(list)) for start, end in zip(events['start'], events['end'])]
dfEveSen['first'+sensor]=dfEveSen[sensor+'values'].apply(lambda x: x[0])
dfEveSen['last'+sensor]=dfEveSen[sensor+'values'].apply(lambda x: x[len(x)-1])
dfEveSen['min'+sensor]=dfEveSen[sensor+'values'].apply(lambda x: min(x))
dfEveSen['max'+sensor]=dfEveSen[sensor+'values'].apply(lambda x: max(x))
dfEveSen['mean'+sensor]=dfEveSen[sensor+'values'].apply(lambda x: mean(x))
#We get the data of dfEveSen to create a MultiIndex dataframe
dataa=[dfEveSen[colum] for colum in dfEveSen.columns]
dataa=np.array(dataa)
#we define the the second indexed row ['Values','Open','Close','Min' ,'Max', 'Mean']
A = np.array( ['Values','Open','Close','Min' ,'Max', 'Mean']*3)
#we define the the first indexed row: ['Sensor 1', 'Sensor 2', 'Sensor 3']
B=np.repeat(sensors.columns[1:],6)
#We create the MultiIndex dataframe called sensorevent
sensorevent = pd.DataFrame(data=dataa.T, columns=pd.MultiIndex.from_tuples(zip(B,A)))
sensorevent.index.name = 'event'
sensorevent.index +=1
print(sensorevent)
#if you want to erase the column of values try this:
#sensorevent = sensorevent.drop('Values', axis=1, level=1)
#print(sensorevent)
输出:
Sensor 1 Sensor 2 Sensor 3
Values Open Close Min Max Mean Values Open Close Min Max Mean Values Open Close Min Max Mean
event
1 [80, 80, 69] 80 69 69 80 76.3333 [4, 5, 9] 4 9 4 9 6 [0, 0, 1] 0 1 0 1 0.333333
2 [76, 62, 80, 64] 76 64 62 80 70.5 [3, 8, 8, 7] 3 7 3 8 6.5 [0, 1, 0, 1] 0 1 0 1 0.5
首先,我们从事件数据帧 (df_e
Start
和End
创建一个IntervalIndex
。使用get_indexer
我们从df_e
获取事件编号,并将它们作为新列分配给传感器数据帧 (df_s
(。这里重要的是,get_indexer
返回缺失值的-1
,因此我们必须在df_e
末尾为缺失事件添加相应的行,以便iloc[-1]
返回此行而不是原始数据的最后一行。然后我们简单地按事件编号分组。
idx = pd.IntervalIndex.from_arrays(df_e.Start, df_e.End, 'both')
df_s.assign(event=df_e.append(pd.Series(dtype='Int64'), ignore_index=True).iloc[idx.get_indexer(df_s.Datetime), 0].values).groupby('event')[['Sensor 1', 'Sensor 2', 'Sensor 3']].agg(['first', 'last', 'min', 'max', 'mean'])
例:
import pandas as pd
import io
s_e = """Event Number Start End
1 6/1/2020 0:00 6/1/2020 0:02
2 6/1/2020 0:05 6/1/2020 0:08"""
s_s = """ Datetime Sensor 1 Sensor 2 Sensor 3
6/1/2020 0:00 80 4 0
6/1/2020 0:01 80 5 0
6/1/2020 0:02 69 9 1
6/1/2020 0:03 72 8 0
6/1/2020 0:04 60 9 0
6/1/2020 0:05 76 3 0
6/1/2020 0:06 62 8 1
6/1/2020 0:07 80 8 0
6/1/2020 0:08 64 7 1"""
df_e = pd.read_csv(io.StringIO(s_e), sep='ss+', parse_dates=[1,2], engine='python')
df_s = pd.read_csv(io.StringIO(s_s), sep='ss+', parse_dates=[0], engine='python')
idx = pd.IntervalIndex.from_arrays(df_e.Start, df_e.End, 'both')
df_s.assign(event=df_e.append(pd.Series(dtype='Int64'),ignore_index=True).iloc[idx.get_indexer(df_s.Datetime),0].values).groupby('event')[['Sensor 1', 'Sensor 2', 'Sensor 3']].agg(['first', 'last', 'min', 'max', 'mean'])
结果:
Sensor 1 Sensor 2 Sensor 3
first last min max mean first last min max mean first last min max mean
event
1 80 69 69 80 76.333333 4 9 4 9 6.0 0 1 0 1 0.333333
2 76 64 62 80 70.500000 3 7 3 8 6.5 0 1 0 1 0.500000
此解决方案适用于大型数据集。对于 100K 行传感器数据和 5K 事件,需要 296 毫秒,而另一个
pd.between
答案需要 16.6 秒。