Как конвертировать несколько, если еще цикл для понимания списка в Python - PullRequest
0 голосов
/ 19 сентября 2018

Я использую следующий цикл if для создания получасовых интервалов примерно для 1 миллиона наблюдений, что отнимает уйму времени.Вот мой цикл if

def half_hourly_buckets(dataframe,time_column):
   dataframe[time_column] = pd.to_datetime(dataframe[time_column],format = '%H:%M:%S').dt.time
   for j in range(len(dataframe)):
    x = dataframe.loc[j,time_column]
    if (x >= datetime.time(0,0,1)) & (x <= datetime.time(0,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "00:00:01 - 00:30:00"
    elif (x >= datetime.time(0,30,1)) & (x <= datetime.time(1,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "00:30:01 - 01:00:00"
    elif (x >= datetime.time(1,0,1)) & (x <= datetime.time(1,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "01:00:01 - 01:30:00"
    elif (x >= datetime.time(1,30,1)) & (x <= datetime.time(2,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "01:30:01 - 02:00:00"
    elif (x >= datetime.time(2,0,1)) & (x <= datetime.time(2,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "02:00:01 - 02:30:00"
    elif (x >= datetime.time(2,30,1)) & (x <= datetime.time(3,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "02:30:01 - 03:00:00"
    elif (x >= datetime.time(3,0,1)) & (x <= datetime.time(3,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "03:00:01 - 03:30:00"
    elif (x >= datetime.time(3,30,1)) & (x <= datetime.time(4,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "03:30:01 - 04:00:00"
    elif (x >= datetime.time(4,0,1)) & (x <= datetime.time(4,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "04:00:01 - 04:30:00"
    elif (x >= datetime.time(4,30,1)) & (x <= datetime.time(5,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "04:30:01 - 05:00:00"
    elif (x >= datetime.time(5,0,1)) & (x <= datetime.time(5,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "05:00:01 - 05:30:00"
    elif (x >= datetime.time(5,30,1)) & (x <= datetime.time(6,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "05:30:01 - 06:00:00"
    elif (x >= datetime.time(6,0,1)) & (x <= datetime.time(6,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "06:00:01 - 06:30:00"
    elif (x >= datetime.time(6,30,1)) & (x <= datetime.time(7,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "06:30:01 - 07:00:00"
    elif (x >= datetime.time(7,0,1)) & (x <= datetime.time(7,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "07:00:01 - 07:30:00"
    elif (x >= datetime.time(7,30,1)) & (x <= datetime.time(8,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "07:30:01 - 08:00:00"
    elif (x >= datetime.time(8,0,1)) & (x <= datetime.time(8,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "08:00:01 - 08:30:00"
    elif (x >= datetime.time(8,30,1)) & (x <= datetime.time(9,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "08:30:01 - 09:00:00"
    elif (x >= datetime.time(9,0,1)) & (x <= datetime.time(9,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "09:00:01 - 09:30:00"
    elif (x >= datetime.time(9,30,1)) & (x <= datetime.time(10,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "09:30:01 - 10:00:00"
    elif (x >= datetime.time(10,0,1)) & (x <= datetime.time(10,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "10:00:01 - 10:30:00"
    elif (x >= datetime.time(10,30,1)) & (x <= datetime.time(11,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "10:30:01 - 11:00:00"
    elif (x >= datetime.time(11,0,1)) & (x <= datetime.time(11,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "11:00:01 - 11:30:00"
    elif (x >= datetime.time(11,30,1)) & (x <= datetime.time(12,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "11:30:01 - 12:00:00"
    elif (x >= datetime.time(12,0,1)) & (x <= datetime.time(12,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "12:00:01 - 12:30:00"
    elif (x >= datetime.time(12,30,1)) & (x <= datetime.time(13,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "12:30:01 - 13:00:00"
    elif (x >= datetime.time(13,0,1)) & (x <= datetime.time(13,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "13:00:01 - 13:30:00"
    elif (x >= datetime.time(13,30,1)) & (x <= datetime.time(14,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "13:30:01 - 14:00:00"
    elif (x >= datetime.time(14,0,1)) & (x <= datetime.time(14,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "14:00:01 - 14:30:00"
    elif (x >= datetime.time(14,30,1)) & (x <= datetime.time(15,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "14:30:01 - 15:00:00"
    elif (x >= datetime.time(15,0,1)) & (x <= datetime.time(15,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "15:00:01 - 15:30:00"
    elif (x >= datetime.time(15,30,1)) & (x <= datetime.time(16,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "15:30:01 - 16:00:00"
    elif (x >= datetime.time(16,0,1)) & (x <= datetime.time(16,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "16:00:01 - 16:30:00"
    elif (x >= datetime.time(16,30,1)) & (x <= datetime.time(17,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "16:30:01 - 17:00:00"
    elif (x >= datetime.time(17,0,1)) & (x <= datetime.time(17,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "17:00:01 - 17:30:00"
    elif (x >= datetime.time(17,30,1)) & (x <= datetime.time(18,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "17:30:01 - 18:00:00"
    elif (x >= datetime.time(18,0,1)) & (x <= datetime.time(18,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "18:00:01 - 18:30:00"
    elif (x >= datetime.time(18,30,1)) & (x <= datetime.time(19,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "18:30:01 - 19:00:00"
    elif (x >= datetime.time(19,0,1)) & (x <= datetime.time(19,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "19:00:01 - 19:30:00"
    elif (x >= datetime.time(19,30,1)) & (x <= datetime.time(20,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "19:30:01 - 20:00:00"
    elif (x >= datetime.time(20,0,1)) & (x <= datetime.time(20,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "20:00:01 - 20:30:00"
    elif (x >= datetime.time(20,30,1)) & (x <= datetime.time(21,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "20:30:01 - 21:00:00"
    elif (x >= datetime.time(21,0,1)) & (x <= datetime.time(21,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "21:00:01 - 21:30:00"
    elif (x >= datetime.time(21,30,1)) & (x <= datetime.time(22,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "21:30:01 - 22:00:00"
    elif (x >= datetime.time(22,0,1)) & (x <= datetime.time(22,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "22:00:01 - 22:30:00"
    elif (x >= datetime.time(22,30,1)) & (x <= datetime.time(23,0,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "22:30:01 - 23:00:00"
    elif (x >= datetime.time(23,0,1)) & (x <= datetime.time(23,30,0)):
        dataframe.loc[j,'half_hourly_bucket'] = "23:00:01 - 23:30:00"
    else:
        dataframe.loc[j,'half_hourly_bucket'] = "23:30:01 - 00:00:00"
return dataframe

Есть ли способ избежать этого цикла и увеличить скорость обработки?

Ответы [ 8 ]

0 голосов
/ 20 сентября 2018

Чтобы дать наиболее прямой ответ на ваш вопрос: вы можете переместить код вычисления бина в вспомогательную функцию, а затем использовать метод .apply() Панда, чтобы применить его ко всем элементам серии.Это будет выполняться намного быстрее, чем ваш цикл, в основном потому, что используемые в настоящее время инкрементные назначения очень медленные.Ниже приведен пример того, как это сделать, на основе вашего исходного кода.

Этот код обрабатывает 500 000 строк примерно за 5 секунд на моем компьютере.Вы можете ускорить его, используя более эффективные методы для расчета бинов;Я привел пример в другом ответе, который занимает около 2 секунд.

df['half_hourly_bucket'] = df['time'].apply(make_bin)

, где make_bin() определяется через

def make_bin(x):
    if (x >= datetime.time(0,0,1)) & (x <= datetime.time(0,30,0)):
        bin = "00:00:01 - 00:30:00"
    elif (x >= datetime.time(0,30,1)) & (x <= datetime.time(1,0,0)):
        bin = "00:30:01 - 01:00:00"
    elif (x >= datetime.time(1,0,1)) & (x <= datetime.time(1,30,0)):
        bin = "01:00:01 - 01:30:00"
    elif (x >= datetime.time(1,30,1)) & (x <= datetime.time(2,0,0)):
        bin = "01:30:01 - 02:00:00"
    elif (x >= datetime.time(2,0,1)) & (x <= datetime.time(2,30,0)):
        bin = "02:00:01 - 02:30:00"
    elif (x >= datetime.time(2,30,1)) & (x <= datetime.time(3,0,0)):
        bin = "02:30:01 - 03:00:00"
    elif (x >= datetime.time(3,0,1)) & (x <= datetime.time(3,30,0)):
        bin = "03:00:01 - 03:30:00"
    elif (x >= datetime.time(3,30,1)) & (x <= datetime.time(4,0,0)):
        bin = "03:30:01 - 04:00:00"
    elif (x >= datetime.time(4,0,1)) & (x <= datetime.time(4,30,0)):
        bin = "04:00:01 - 04:30:00"
    elif (x >= datetime.time(4,30,1)) & (x <= datetime.time(5,0,0)):
        bin = "04:30:01 - 05:00:00"
    elif (x >= datetime.time(5,0,1)) & (x <= datetime.time(5,30,0)):
        bin = "05:00:01 - 05:30:00"
    elif (x >= datetime.time(5,30,1)) & (x <= datetime.time(6,0,0)):
        bin = "05:30:01 - 06:00:00"
    elif (x >= datetime.time(6,0,1)) & (x <= datetime.time(6,30,0)):
        bin = "06:00:01 - 06:30:00"
    elif (x >= datetime.time(6,30,1)) & (x <= datetime.time(7,0,0)):
        bin = "06:30:01 - 07:00:00"
    elif (x >= datetime.time(7,0,1)) & (x <= datetime.time(7,30,0)):
        bin = "07:00:01 - 07:30:00"
    elif (x >= datetime.time(7,30,1)) & (x <= datetime.time(8,0,0)):
        bin = "07:30:01 - 08:00:00"
    elif (x >= datetime.time(8,0,1)) & (x <= datetime.time(8,30,0)):
        bin = "08:00:01 - 08:30:00"
    elif (x >= datetime.time(8,30,1)) & (x <= datetime.time(9,0,0)):
        bin = "08:30:01 - 09:00:00"
    elif (x >= datetime.time(9,0,1)) & (x <= datetime.time(9,30,0)):
        bin = "09:00:01 - 09:30:00"
    elif (x >= datetime.time(9,30,1)) & (x <= datetime.time(10,0,0)):
        bin = "09:30:01 - 10:00:00"
    elif (x >= datetime.time(10,0,1)) & (x <= datetime.time(10,30,0)):
        bin = "10:00:01 - 10:30:00"
    elif (x >= datetime.time(10,30,1)) & (x <= datetime.time(11,0,0)):
        bin = "10:30:01 - 11:00:00"
    elif (x >= datetime.time(11,0,1)) & (x <= datetime.time(11,30,0)):
        bin = "11:00:01 - 11:30:00"
    elif (x >= datetime.time(11,30,1)) & (x <= datetime.time(12,0,0)):
        bin = "11:30:01 - 12:00:00"
    elif (x >= datetime.time(12,0,1)) & (x <= datetime.time(12,30,0)):
        bin = "12:00:01 - 12:30:00"
    elif (x >= datetime.time(12,30,1)) & (x <= datetime.time(13,0,0)):
        bin = "12:30:01 - 13:00:00"
    elif (x >= datetime.time(13,0,1)) & (x <= datetime.time(13,30,0)):
        bin = "13:00:01 - 13:30:00"
    elif (x >= datetime.time(13,30,1)) & (x <= datetime.time(14,0,0)):
        bin = "13:30:01 - 14:00:00"
    elif (x >= datetime.time(14,0,1)) & (x <= datetime.time(14,30,0)):
        bin = "14:00:01 - 14:30:00"
    elif (x >= datetime.time(14,30,1)) & (x <= datetime.time(15,0,0)):
        bin = "14:30:01 - 15:00:00"
    elif (x >= datetime.time(15,0,1)) & (x <= datetime.time(15,30,0)):
        bin = "15:00:01 - 15:30:00"
    elif (x >= datetime.time(15,30,1)) & (x <= datetime.time(16,0,0)):
        bin = "15:30:01 - 16:00:00"
    elif (x >= datetime.time(16,0,1)) & (x <= datetime.time(16,30,0)):
        bin = "16:00:01 - 16:30:00"
    elif (x >= datetime.time(16,30,1)) & (x <= datetime.time(17,0,0)):
        bin = "16:30:01 - 17:00:00"
    elif (x >= datetime.time(17,0,1)) & (x <= datetime.time(17,30,0)):
        bin = "17:00:01 - 17:30:00"
    elif (x >= datetime.time(17,30,1)) & (x <= datetime.time(18,0,0)):
        bin = "17:30:01 - 18:00:00"
    elif (x >= datetime.time(18,0,1)) & (x <= datetime.time(18,30,0)):
        bin = "18:00:01 - 18:30:00"
    elif (x >= datetime.time(18,30,1)) & (x <= datetime.time(19,0,0)):
        bin = "18:30:01 - 19:00:00"
    elif (x >= datetime.time(19,0,1)) & (x <= datetime.time(19,30,0)):
        bin = "19:00:01 - 19:30:00"
    elif (x >= datetime.time(19,30,1)) & (x <= datetime.time(20,0,0)):
        bin = "19:30:01 - 20:00:00"
    elif (x >= datetime.time(20,0,1)) & (x <= datetime.time(20,30,0)):
        bin = "20:00:01 - 20:30:00"
    elif (x >= datetime.time(20,30,1)) & (x <= datetime.time(21,0,0)):
        bin = "20:30:01 - 21:00:00"
    elif (x >= datetime.time(21,0,1)) & (x <= datetime.time(21,30,0)):
        bin = "21:00:01 - 21:30:00"
    elif (x >= datetime.time(21,30,1)) & (x <= datetime.time(22,0,0)):
        bin = "21:30:01 - 22:00:00"
    elif (x >= datetime.time(22,0,1)) & (x <= datetime.time(22,30,0)):
        bin = "22:00:01 - 22:30:00"
    elif (x >= datetime.time(22,30,1)) & (x <= datetime.time(23,0,0)):
        bin = "22:30:01 - 23:00:00"
    elif (x >= datetime.time(23,0,1)) & (x <= datetime.time(23,30,0)):
        bin = "23:00:01 - 23:30:00"
    else:
        bin = "23:30:01 - 00:00:00"
    return bin
0 голосов
/ 19 сентября 2018

Вы можете сделать это очень быстро с помощью векторизованных операций в Pandas.Единственная хитрость - преобразование ваших datetime.time значений в метки времени, которые могут использовать Pandas.Вот код, который сделает всю работу за 4 секунды:

import datetime, random
import pandas as pd, numpy as np

# create random times
df = pd.DataFrame({'time': [
    datetime.time(int(24 * h), int(60 * m), int(60 * s)) 
    for h, m, s in np.random.rand(500000, 3)
]})

def half_hourly_buckets(dataframe, time_column):
    # convert time values to datetimes on arbitrary date
    base_date = datetime.datetime(2000, 1, 1)
    dt = dataframe[time_column].apply(
        lambda t: datetime.datetime.combine(base_date, t)
    )
    # assign corresponding bins
    one_second = pd.Timedelta(seconds=1)
    thirty_minutes = pd.Timedelta(minutes=30)
    bin = (dt - one_second).dt.floor('30T')
    dataframe['half_hourly_bucket'] = (
        (bin + one_second).dt.strftime("%H:%M:%S") 
        + ' - '
        + (bin + thirty_minutes).dt.strftime("%H:%M:%S") 
    )

half_hourly_buckets(df, 'time')
df
#             time   half_hourly_bucket
# 0       07:00:49  07:00:01 - 07:30:00
# 1       06:16:19  06:00:01 - 06:30:00
# 2       06:17:06  06:00:01 - 06:30:00
# 3       17:28:31  17:00:01 - 17:30:00
# ...          ...                  ...
# 739     18:00:01  18:00:01 - 18:30:00
# ...          ...                  ...
# 4259    00:00:00  23:30:01 - 00:00:00
# ...          ...                  ...
# 4520    17:30:00  17:00:01 - 17:30:00
# ...          ...                  ...
0 голосов
/ 19 сентября 2018

Вы можете сделать это очень быстро, создав более эффективную вспомогательную функцию для расчета бинов, а затем используя функцию Pandas .apply для ее вызова.Вот пример, который запускается примерно за 2 секунды.

Обратите внимание, что в отличие от некоторых других ответов, это перемещает: 00: 00 и: 30: 00 раз в корзину за полчаса, как показано в вашем коде.

import datetime, random
import pandas as pd, numpy as np

# create random times
df = pd.DataFrame({'time': [
    datetime.time(int(24 * h), int(60 * m), int(60 * s)) 
    for h, m, s in np.random.rand(500000, 3)
]})

def make_bin(t):
    h, m, s = t.hour, t.minute, t.second
    # move the first second of each half-hour back into the prior bin
    if s == 0 and m in {0, 30}:
        if m == 0:
            h = (h - 1) % 24
            m = 59
        else:
            m = 29
    # is this in the first half of the hour?
    first_half = m < 30
    # calculate bin start and end
    start = datetime.time(h, 0 if first_half else 30, 1)
    end = datetime.time(
        h if first_half else (h + 1) % 24,
        30 if first_half else 0,
        0
    )
    return '{} - {}'.format(start, end)

def half_hourly_buckets(dataframe, time_column):
    dataframe['half_hourly_bucket'] = dataframe[time_column].apply(make_bin)

half_hourly_buckets(df, 'time')
df
#             time   half_hourly_bucket
# 0       02:07:13  02:00:01 - 02:30:00
# 1       21:52:35  21:30:01 - 22:00:00
# 2       07:41:36  07:30:01 - 08:00:00
# 3       20:41:36  20:30:01 - 21:00:00
# ...
# 761     17:00:00  16:30:01 - 17:00:00
# 1460    17:30:00  17:00:01 - 17:30:00
# ...
# 219253  00:00:00  23:30:01 - 00:00:00
# ...
0 голосов
/ 19 сентября 2018

Вы можете использовать pandas cut для группировки данных с интервалом в полчаса

dates = pd.date_range(end = '09/18/2018', periods = 10000, freq='S')
df = pd.DataFrame({'datetime': np.random.choice(dates, 10000)})

bins = pd.date_range(df.datetime.dt.floor('30T').min(), df.datetime.dt.ceil('30T').max(), freq = '30T')
pd.cut(df.datetime, bins = bins)

Вы получаете

0       (2018-09-17 22:30:00, 2018-09-17 23:00:00]
1       (2018-09-17 22:00:00, 2018-09-17 22:30:00]
2       (2018-09-17 21:00:00, 2018-09-17 21:30:00]
3       (2018-09-17 21:30:00, 2018-09-17 22:00:00]
4       (2018-09-17 22:00:00, 2018-09-17 22:30:00]
5                (2018-09-17 23:30:00, 2018-09-18]
6       (2018-09-17 22:00:00, 2018-09-17 22:30:00]
7       (2018-09-17 22:00:00, 2018-09-17 22:30:00]

Бункеры могут быть легко сгруппированы для агрегации

dates = pd.date_range(end = '09/18/2018', periods = 10000, freq='S')
df = pd.DataFrame({'id' : np.random.randint(10, 1000, 10000),'datetime': np.random.choice(dates, 10000)})

bins = pd.date_range(df.datetime.dt.floor('30T').min(), df.datetime.dt.ceil('30T').max(), freq = '30T')
df.groupby(['id', pd.cut(df.datetime, bins = bins)]).size()

id   datetime                                  
10   (2018-09-17 21:00:00, 2018-09-17 21:30:00]    2
     (2018-09-17 21:30:00, 2018-09-17 22:00:00]    1
     (2018-09-17 22:00:00, 2018-09-17 22:30:00]    1
     (2018-09-17 22:30:00, 2018-09-17 23:00:00]    3
     (2018-09-17 23:00:00, 2018-09-17 23:30:00]    4
11   (2018-09-17 21:30:00, 2018-09-17 22:00:00]    1
     (2018-09-17 22:00:00, 2018-09-17 22:30:00]    1
     (2018-09-17 22:30:00, 2018-09-17 23:00:00]    1
     (2018-09-17 23:30:00, 2018-09-18]             1
0 голосов
/ 19 сентября 2018

Сначала создайте отсортированный список всех этих временных интервалов в виде кортежей:

>>> times=[('00:00:01', '00:30:00'), ('00:30:01', '01:00:00'), ('01:00:01', '01:30:00'), ('01:30:01', '02:00:00'), ('02:00:01', '02:30:00'), ('02:30:01', '03:00:00'), ('03:00:01', '03:30:00'), ('03:30:01', '04:00:00'), ('04:00:01', '04:30:00'), ('04:30:01', '05:00:00'), ('05:00:01', '05:30:00'), ('05:30:01', '06:00:00'), ('06:00:01', '06:30:00'), ('06:30:01', '07:00:00'), ('07:00:01', '07:30:00'), ('07:30:01', '08:00:00'), ('08:00:01', '08:30:00'), ('08:30:01', '09:00:00'), ('09:00:01', '09:30:00'), ('09:30:01', '10:00:00'), ('10:00:01', '10:30:00'), ('10:30:01', '11:00:00'), ('11:00:01', '11:30:00'), ('11:30:01', '12:00:00'), ('12:00:01', '12:30:00'), ('12:30:01', '13:00:00'), ('13:00:01', '13:30:00'), ('13:30:01', '14:00:00'), ('14:00:01', '14:30:00'), ('14:30:01', '15:00:00'), ('15:00:01', '15:30:00'), ('15:30:01', '16:00:00'), ('16:00:01', '16:30:00'), ('16:30:01', '17:00:00'), ('17:00:01', '17:30:00'), ('17:30:01', '18:00:00'), ('18:00:01', '18:30:00'), ('18:30:01', '19:00:00'), ('19:00:01', '19:30:00'), ('19:30:01', '20:00:00'), ('20:00:01', '20:30:00'), ('20:30:01', '21:00:00'), ('21:00:01', '21:30:00'), ('21:30:01', '22:00:00'), ('22:00:01', '22:30:00'), ('22:30:01', '23:00:00'), ('23:00:01', '23:30:00'), ('23:30:01', '00:00:00')]

Затем индекс на основе правого значения:

>>> idx=[t[1] for t in times]

Затем вы можете использоватьМодуль bisect для выбора правильного сегмента:

>>> times[bisect.bisect_left(idx,'00:31:00')]
('00:30:01', '01:00:00')

Учитывая, что значение 00:00:00 входит в последний интервал (как вы написали в примере), вы должны проверить это отдельно:

>>> bucket = ('23:30:01', '00:00:00') if ts=='00:00:00' else times[bisect.bisect_left(idx, ts)]

Модуль bisect очень быстрый и эффективный.Возможно, в несколько сотен раз быстрее, чем другие нативные методы Python, чтобы делать подобные вещи.

0 голосов
/ 19 сентября 2018

Вы можете выбрать другой подход и использовать timedelta для определения сегмента, что значительно упрощает этот код:

from datetime import datetime, timedelta


def ceil_dt(dt, delta):
    return dt + (datetime.min - dt) % delta


def floor_dt(dt, delta):
    return dt - (dt - datetime.min) % delta


now = datetime.now()
print(now)
print(
    floor_dt(now, timedelta(minutes=30)), ceil_dt(now, timedelta(minutes=30))
)

https://repl.it/@ryanpcmcquen/TwinHelplessLifecycles-1

floor_dt дает вам началоведра и ceil_dt дает вам его конец.

0 голосов
/ 19 сентября 2018

Вам вообще не нужны дела.

 x = dataframe.loc[j,time_column]
 if x > datetime.time(23,30,0):
     dataframe.loc[j,'half_hourly_bucket'] = "23:30:01 - 00:00:00"
 else:
     past = x.minute >= 30
     min_hour = str(x.hour).zfill(2)
     max_hour = str(x.hour+1 if past else x.hour).zfill(2)
     min_time = ':30:01' if past else ':00:01'
     max_time = ':00:00' if past else ':30:00'
     dataframe.loc[j,'half_hourly_bucket'] = min_hour+min_time+' - '+max_hour+max_time
0 голосов
/ 19 сентября 2018

Во-первых, вы делаете вдвое больше сравнений, необходимых для этого подхода.Если вы не пройдете первый тест, вы уже знаете, что

x >= datetime.time(0,30,1))

, поэтому вам не придется тестировать его второй раз на следующем elif.

Во-вторых,из-за того, что вы используете обычные сегменты, вы можете определить, какой сегмент вам нужен, беря количество секунд и используя целочисленную часть результата деления этого на тридцать минут.Предполагая, что x является объектом времени, вы могли бы сделать что-то вроде этого:

bucket_number = int((datetime.datetime.combine(datetime.date.min, x) -
                     datetime.datetime.combine(datetime.date.min, datetime.time(0))
                    ).total_seconds() / (30 * 60))
bucket_start = datetime.datetime.combine(datetime.date.min, datetime.time(0)) + \
               datetime.timedelta(seconds = bucket_number * 30 * 60)
bucket_end = datetime.datetime.combine(datetime.date.min, datetime.time(0)) + \
             datetime.timedelta(seconds = (bucket_number + 1) * 30 * 60)
dataframe.loc[j,'half_hourly_bucket'] = "{} - {}".format(bucket_start.strftime('%H:%M:%S'),
                                                         bucket_end.strftime('%H:%M:%S'))

Это устранит необходимость в каких-либо тестах.

Примечание: большая часть тяжелой работы здесь заключается в том, чтотрудно работать с time объектами.Если бы вы могли использовать datetime объекты вместо этого, это было бы намного проще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...