Полный кадр данных Pandas с нулевыми значениями для больших наборов данных - PullRequest
0 голосов
/ 26 октября 2018

У меня есть датафрейм, который выглядит так:

>> df
index  week  day  hour  count
5      10    2    10    70
5      10    3    11    80
7      10    2    18    15
7      10    2    19    12

, где week - неделя года, day - день недели (0-6) и hour - час дня (0-23). Однако, поскольку я планирую преобразовать это в трехмерный массив (неделя x день x час) позже, я должен включить часы, в которых нет элементов в столбце count. Пример:

>> target_df
index  week  day  hour  count
5      10    0    0     0
5      10    0    1     0
...
5      10    2    10    70
5      10    2    11    0
...
7      10    0    0     0
...
...

и так далее. Что я делаю, это создаю фиктивный фрейм данных, содержащий все возможные комбинации индекс-неделя-день-час (в основном target_df без столбца count):

>> dummy_df

index  week  day  hour
5      10    0    0   
5      10    0    1   
...
5      10    2    10  
5      10    2    11
...
7      10    0    0 
...
...

, а затем с помощью

target_df = pd.merge(df, dummy_df, on=['index','week','day','hour'], how='outer').fillna(0)

Это отлично работает для небольших наборов данных, но я работаю с большим количеством строк. С делом, над которым я сейчас работаю, я получаю 82M строк для dummy_df и target_df, и это мучительно медленно.

РЕДАКТИРОВАТЬ : Самая медленная часть на самом деле создает dummy_df !!! Я могу сгенерировать отдельные списки, но объединение их в фрейм данных панд - самая медленная часть.

num_weeks = len(week_list)
num_idxs = len(df['index'].unique())
print('creating dummies')
_dummy_idxs = list(itertools.chain.from_iterable(
                   itertools.repeat(x, 24*7*num_weeks) for x in df['index'].unique()))
print('\t_dummy_idxs')
_dummy_weeks = list(itertools.chain.from_iterable(
                   itertools.repeat(x, 24*7) for x in week_list)) * num_idxs
print('\t_dummy_weeks')
_dummy_days = list(itertools.chain.from_iterable(
                   itertools.repeat(x, 24) for x in range(0,7))) * num_weeks * num_idxs
print('\t_dummy_days')
_dummy_hours = list(range(0,24)) * 7 * num_weeks * num_idxs
print('\t_dummy_hours')
print('Creating dummy_hour_df with {0} rows...'.format(len(_dummy_hours)))
# the part below takes the longest time
dummy_hour_df = pd.DataFrame({'index': _dummy_idxs, 'week': _dummy_weeks, 'day': _dummy_days, 'hour': _dummy_hours})
print('dummy_hour_df completed')

Есть ли более быстрый способ сделать это?

1 Ответ

0 голосов
/ 31 октября 2018

В качестве альтернативы вы можете использовать itertools.product для создания dummy_df как произведение списков:

import itertools
index = range(100)
weeks = range(53)
days = range(7)
hours = range(24)

dummy_df = pd.DataFrame(list(itertools.product(index, weeks, days, hours)), columns=['index','week','day','hour'])

dummy_df.head()

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