Создание динамического массива numpy с использованием двух существующих массивов

Я хочу умножить два массива (а не их значения). В этом случае у меня есть массив последовательных дат, которые могут варьироваться, и еще один массив значений от 0 до 23 (т.е. часов).

a = np.arange(np.datetime64('2024-01-01'), np.datetime64('2024-01-11')) и b = np.linspace(0, 23, 24)

Как мне объединить их в новый массив так, чтобы (в приведенном выше примере) он давал массив из 240 строк, каждые 24 строки — это заданная дата и последовательные часы от 0 до 23?

Это даст следующий результат: array([['2024-01-01', 0],['2024-01-01', 1] ... ['2024-01-10', 22],['2024-01-10', 23]])

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
50
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

IIUC, конвертируйте b в массив timedelta64 , затем транслируйте сложение и сгладьте с помощью ravel:

out = (a[:, None] + b*np.timedelta64(1, 'h')).ravel()

Или:

out = np.add.outer(a, b*np.timedelta64(1, 'h')).ravel()

Выход:

array(['2024-01-01T00', '2024-01-01T01', '2024-01-01T02', '2024-01-01T03',
       '2024-01-01T04', '2024-01-01T05', '2024-01-01T06', '2024-01-01T07',
       '2024-01-01T08', '2024-01-01T09', '2024-01-01T10', '2024-01-01T11',
       ...,
       '2024-01-10T20', '2024-01-10T21', '2024-01-10T22', '2024-01-10T23'],
      dtype='datetime64[h]')

Если вы хотите столбцы с парами даты/часов:

out = np.c_[np.repeat(a, len(b)).astype(object), np.tile(b, len(a))]

array([[datetime.date(2024, 1, 1), 0.0],
       [datetime.date(2024, 1, 1), 1.0],
       [datetime.date(2024, 1, 1), 2.0],
       [datetime.date(2024, 1, 1), 3.0],
       ...,
       [datetime.date(2024, 1, 1), 22.0],
       [datetime.date(2024, 1, 1), 23.0],
       [datetime.date(2024, 1, 2), 0.0],
       [datetime.date(2024, 1, 2), 1.0],
       ...,
       [datetime.date(2024, 1, 10), 21.0],
       [datetime.date(2024, 1, 10), 22.0],
       [datetime.date(2024, 1, 10), 23.0]], dtype=object)

Но это не очень хорошее использование numpy IMO (в этом случае лучше использовать структурированный массив или Pandas DataFrame):

out = np.empty(len(a)*len(b), dtype=[('date', a.dtype), ('hour', b.dtype)])
out['date'] = np.repeat(a, len(b))
out['hour'] = np.tile(b, len(a))

array([('2024-01-01',  0.), ('2024-01-01',  1.), ('2024-01-01',  2.),
       ('2024-01-01',  3.), ('2024-01-01',  4.), ('2024-01-01',  5.),
       ('2024-01-01',  6.), ('2024-01-01',  7.), ('2024-01-01',  8.),
       ...,
       ('2024-01-10', 18.), ('2024-01-10', 19.), ('2024-01-10', 20.),
       ('2024-01-10', 21.), ('2024-01-10', 22.), ('2024-01-10', 23.)],
      dtype=[('date', '<M8[D]'), ('hour', '<f8')])

Или:

import pandas as pd

out = pd.DataFrame({'date': a}).merge(pd.DataFrame({'hour': b}), how='cross')

          date  hour
0   2024-01-01   0.0
1   2024-01-01   1.0
2   2024-01-01   2.0
3   2024-01-01   3.0
4   2024-01-01   4.0
..         ...   ...
235 2024-01-10  19.0
236 2024-01-10  20.0
237 2024-01-10  21.0
238 2024-01-10  22.0
239 2024-01-10  23.0

[240 rows x 2 columns]

Спасибо за это Мозвей. Это работает как решение, но я надеялся получить два столбца [0] = дата (- которые будут повторяться более 24 строк) и [1] час от 0 до 23 для этой даты.

Seamus 29.07.2024 14:57

@Seamus, пожалуйста, отредактируйте свой вопрос, добавив явный ожидаемый результат (вы можете уменьшить его до 2 дней и 3 часов, чтобы пример был коротким)

mozway 29.07.2024 14:58

Да, я согласен с тобой. Я ищу самый быстрый способ построить данные за год на основе трех переменных (0-7, 1-30, 0-30), что в конечном итоге даст> 65 миллионов строк :-(

Seamus 29.07.2024 15:08

Я добавил альтернативные подходы с использованием структурированных массивов и панд, которые следует предпочитать массиву объектов.

mozway 29.07.2024 15:08

Еще раз спасибо Мозвей. Мне нужно провести исследование!!! но ваша помощь была значительной. Очень признателен.

Seamus 29.07.2024 15:14

Я считаю, что вы пытаетесь достичь декартова произведения двух массивов.

Чтобы получить это, вы можете использовать itertools.product из стандартной библиотеки:

permutations = list(itertools.product(a, b))

Результат:

[
(numpy.datetime64('2024-01-01'), 0),
(numpy.datetime64('2024-01-01'), 1),
(numpy.datetime64('2024-01-01'), 2),
...
]

ЭТО был @robertoschiavone. Спасибо за это. Я не мог придумать математический термин, который искал.

Seamus 01.08.2024 19:43
from sklearn.preprocessing import LabelEncoder as le
import numpy as np
import pandas as pd

# Define the date range and hours
# Create a date range from 1990-01-01 to 1990-01-10
dates = np.arange(np.datetime64('1990-01-01'), np.datetime64('1990-01-11'))  
# Create an array of hours from 0 to 23
hours = np.linspace(0, 23, 24).astype(int)  

# Create label encoders for dates and hours
le_hours = le()
le_dates = le()

# Encode dates and hours
date_encoded = le_dates.fit_transform(dates.astype(str)) 
hour_encoded = le_hours.fit_transform(hours)  

# Create all combinations of dates and hours
 # Repeat each date for all hours
date_repeated = np.repeat(date_encoded, len(hours))
# Tile the hour array for all dates 
hour_tiled = np.tile(hour_encoded, len(dates))  

# Decode the encoded dates and hours back to original format
date_decoded = le_dates.inverse_transform(date_repeated)  
hour_decoded = le_hours.inverse_transform(hour_tiled)  

# Combine dates and hours into a single array
data = np.column_stack([date_decoded, hour_decoded])  
# Create a pandas DataFrame from the array
df = pd.DataFrame(data, columns=['Date', 'Hour']) 
print(df)
'''
           Date Hour
0    1990-01-01    0
1    1990-01-01    1
2    1990-01-01    2
3    1990-01-01    3
4    1990-01-01    4
..          ...  ...
235  1990-01-10   19
236  1990-01-10   20
237  1990-01-10   21
238  1990-01-10   22
239  1990-01-10   23
'''

Спасибо @Soudipta, это довольно элегантное решение. Тем не менее, я реализовал тот вариант, который предложил Mozway, как только он появился. У меня есть скрытое подозрение, что ваш может быть «более правильным», хотя и длиннее в коде.

Seamus 01.08.2024 19:45

Другие вопросы по теме