按自定义和可变长度日期时间范围对 Pandas 数据框进行分箱
Binning Pandas Dataframe by custom and variable length datetime ranges
我正在尝试使用 pd.cut 对在可变时间长度内进行的测试的详细结果行进行分类。 bins 的目的是最终添加一个新列,我可以在其中根据为该测试结果记录的时间戳是否在该测试的定义时间范围内来定义每一行测试结果属于哪个测试。
df 中的数据如下所示
Index DeviceID QuantResult1 QuantResult2 Timestamp
0 15D 7903 387403 2017-10-14 00:28:00
1 15D 3429734 786 2017-10-14 00:29:10
2 15D 2320923 546 2017-10-14 00:31:15
3 15D 232 435869 2017-10-14 00:50:05
4 15D 34032984 12 2017-10-14 01:10:07
到目前为止,我尝试为每个单独的测试创建单独的日期时间范围,这样
test_1 = pd.date_range(start = '2017-10-14 00:20:00', end = '2017-10-14 00:33:15', freq = 'S')
test_2 = pd.date(pd.date_range(start = '2017-10-14 00:49:15', end = '2017-10-14 01:15:15', freq = 'S')
等等
然后我在所有测试中创建了一个 date_ranges 列表
test_list = [test_1,test_2]
然后我尝试使用 pd.cut
df = pd.cut(df['Timestamp'],bins = test_list, labels = ['Test_1','Test_2'])
但是我收到以下错误:
TypeError: <class 'int'> type object 0.
最终我希望数据看起来像这样
Index DeviceID QuantResult1 QuantResult2 Timestamp Test
0 15D 7903 387403 2017-10-14 00:28:00 Test_1
1 15D 3429734 786 2017-10-14 00:29:10 Test_1
2 15D 2320923 546 2017-10-14 00:31:15 Test_1
3 15D 232 435869 2017-10-14 00:50:05 Test_2
4 15D 34032984 12 2017-10-14 01:10:07 Test_2
你能告诉我错误的来源是什么吗?
我已经尝试将 test_list 映射为整数,并在将 df['Timestamp'] 列转换为 np.int64 后与 df 进行比较,如下所示。
test_list_int64 = list(map(np.int64,test_list))
df = pd.cut(df['Timestamp'].astype(np.int64),bins = test_list_int64)
但是这种努力出现了以下错误:
ValueError: operands could not be broadcast together with shapes (1320,) (87480,)
谢谢!
boundary = pd.to_datetime('2017-10-14 00:30:00')
现在使用np.where
test['Test'] = np.where(test['TimeStamp']< boundary, 'test_1', np.where(test['TimeStamp'], 'test_2', None))
输出:
Index DeviceID QuantResult1 QuantResult2 TimeStamp Test
0 15D 7903 387403 2017-10-14 00:28:00 2017-10-14 00:28:00 test_1
1 15D 3429734 786 2017-10-14 00:29:10 2017-10-14 00:29:10 test_1
2 15D 2320923 546 2017-10-14 00:31:15 2017-10-14 00:31:15 test_2
3 15D 232 435869 2017-10-14 00:50:05 2017-10-14 00:50:05 test_2
4 15D 34032984 12 2017-10-14 01:10:07 2017-10-14 01:10:07 test_2
如果您有每个时段的开始和结束时间,那么您真的不需要创建范围。您可以只对日期时间对象使用逻辑。如果你有的话,应该很容易推广到越来越多的测试。
import pandas as pd
start_t1 = pd.to_datetime('2017-10-14 00:20:00')
stop_t1 = pd.to_datetime('2017-10-14 00:33:15')
start_t2 = pd.to_datetime('2017-10-14 00:49:15')
stop_t2 = pd.to_datetime('2017-10-14 01:15:15')
df.loc[(df.Timestamp > start_t1) & (df.Timestamp < stop_t1), 'Test'] = 'Test_1'
df.loc[(df.Timestamp > start_t2) & (df.Timestamp < stop_t2), 'Test'] = 'Test_2'
DeviceID Quant Result2 QuantResult1 Timestamp Test
0 15D 387403 7903 2017-10-14 00:28:00 Test_1
1 15D 786 3429734 2017-10-14 00:29:10 Test_1
2 15D 546 2320923 2017-10-14 00:31:15 Test_1
3 15D 435869 232 2017-10-14 00:50:05 Test_2
4 15D 12 34032984 2017-10-14 01:10:07 Test_2
我正在尝试使用 pd.cut 对在可变时间长度内进行的测试的详细结果行进行分类。 bins 的目的是最终添加一个新列,我可以在其中根据为该测试结果记录的时间戳是否在该测试的定义时间范围内来定义每一行测试结果属于哪个测试。
df 中的数据如下所示
Index DeviceID QuantResult1 QuantResult2 Timestamp
0 15D 7903 387403 2017-10-14 00:28:00
1 15D 3429734 786 2017-10-14 00:29:10
2 15D 2320923 546 2017-10-14 00:31:15
3 15D 232 435869 2017-10-14 00:50:05
4 15D 34032984 12 2017-10-14 01:10:07
到目前为止,我尝试为每个单独的测试创建单独的日期时间范围,这样
test_1 = pd.date_range(start = '2017-10-14 00:20:00', end = '2017-10-14 00:33:15', freq = 'S')
test_2 = pd.date(pd.date_range(start = '2017-10-14 00:49:15', end = '2017-10-14 01:15:15', freq = 'S')
等等
然后我在所有测试中创建了一个 date_ranges 列表
test_list = [test_1,test_2]
然后我尝试使用 pd.cut
df = pd.cut(df['Timestamp'],bins = test_list, labels = ['Test_1','Test_2'])
但是我收到以下错误:
TypeError: <class 'int'> type object 0.
最终我希望数据看起来像这样
Index DeviceID QuantResult1 QuantResult2 Timestamp Test
0 15D 7903 387403 2017-10-14 00:28:00 Test_1
1 15D 3429734 786 2017-10-14 00:29:10 Test_1
2 15D 2320923 546 2017-10-14 00:31:15 Test_1
3 15D 232 435869 2017-10-14 00:50:05 Test_2
4 15D 34032984 12 2017-10-14 01:10:07 Test_2
你能告诉我错误的来源是什么吗?
我已经尝试将 test_list 映射为整数,并在将 df['Timestamp'] 列转换为 np.int64 后与 df 进行比较,如下所示。
test_list_int64 = list(map(np.int64,test_list))
df = pd.cut(df['Timestamp'].astype(np.int64),bins = test_list_int64)
但是这种努力出现了以下错误:
ValueError: operands could not be broadcast together with shapes (1320,) (87480,)
谢谢!
boundary = pd.to_datetime('2017-10-14 00:30:00')
现在使用np.where
test['Test'] = np.where(test['TimeStamp']< boundary, 'test_1', np.where(test['TimeStamp'], 'test_2', None))
输出:
Index DeviceID QuantResult1 QuantResult2 TimeStamp Test
0 15D 7903 387403 2017-10-14 00:28:00 2017-10-14 00:28:00 test_1
1 15D 3429734 786 2017-10-14 00:29:10 2017-10-14 00:29:10 test_1
2 15D 2320923 546 2017-10-14 00:31:15 2017-10-14 00:31:15 test_2
3 15D 232 435869 2017-10-14 00:50:05 2017-10-14 00:50:05 test_2
4 15D 34032984 12 2017-10-14 01:10:07 2017-10-14 01:10:07 test_2
如果您有每个时段的开始和结束时间,那么您真的不需要创建范围。您可以只对日期时间对象使用逻辑。如果你有的话,应该很容易推广到越来越多的测试。
import pandas as pd
start_t1 = pd.to_datetime('2017-10-14 00:20:00')
stop_t1 = pd.to_datetime('2017-10-14 00:33:15')
start_t2 = pd.to_datetime('2017-10-14 00:49:15')
stop_t2 = pd.to_datetime('2017-10-14 01:15:15')
df.loc[(df.Timestamp > start_t1) & (df.Timestamp < stop_t1), 'Test'] = 'Test_1'
df.loc[(df.Timestamp > start_t2) & (df.Timestamp < stop_t2), 'Test'] = 'Test_2'
DeviceID Quant Result2 QuantResult1 Timestamp Test
0 15D 387403 7903 2017-10-14 00:28:00 Test_1
1 15D 786 3429734 2017-10-14 00:29:10 Test_1
2 15D 546 2320923 2017-10-14 00:31:15 Test_1
3 15D 435869 232 2017-10-14 00:50:05 Test_2
4 15D 12 34032984 2017-10-14 01:10:07 Test_2