Я предполагаю, что столбец Дата в df1 имеет тип дата-время . Если нет, преобразуйте его.
Начните с таких подготовительных шагов:
В df2 конвертируйте год / месяц / день столбцы индекс (из datetime тип):
df2 = df2.set_index(pd.to_datetime(df2.year * 10000 + df2.month * 100
+ df2.day, format='%Y%m%d')).drop(columns=['year', 'month', 'day'])
Установите количество дней, для которыхдобавьте столбцы:
nDays = 3
Для демонстрации я установил значение 3 , но вы можете изменить его на 100 или любое другое значение по вашему желанию.
Определить имена столбцов для новых столбцов (первые import itertools ):
cols = [ x + str(y) for x, y in itertools.product(
['max_t', 'min_t', 'rf', 'w'], range(1, nDays + 1)) ]
Определить функцию для создания дополнительных столбцов,для текущей строки:
def fn(row):
d1 = row.Date
d2 = d1 + pd.Timedelta(nDays - 1, 'D')
return pd.Series(df2.loc[d1:d2].values.reshape((1, -1),
order='F').squeeze(), index=cols)
И теперь вся обработка может быть выполнена в инструкции single , применяя вышеуказанную функцию к каждой строке и соединяярезультат для исходного DataFrame:
df1 = df1.join(df1.apply(fn, axis=1))
Довольно краткое и в значительной степени решение pandasonic .
Для демонстрации работы этого решения я изменил yнаши данные немного:
df1:
x0 x1 x2 x3 Date
0 40 31.05 25.5 25.5 2013-01-03
1 35 35.75 36.5 36.5 2013-01-07
df2 (начальное содержание):
year month day maxtemp mintemp rainfall wind
0 2013 1 1 26.2 20.2 0 32.4
1 2013 1 2 22.9 20.3 0 10.0
2 2013 1 3 24.8 18.4 1 28.8
3 2013 1 4 26.6 18.3 2 33.5
4 2013 1 5 28.3 20.9 3 33.4
5 2013 1 6 28.0 21.6 4 32.8
6 2013 1 7 27.5 21.4 5 26.8
7 2013 1 8 42.3 20.9 6 25.5
8 2013 1 9 25.0 21.1 7 20.9
9 2013 1 10 25.4 20.2 8 14.0
df2 (после преобразования):
maxtemp mintemp rainfall wind
2013-01-01 26.2 20.2 0 32.4
2013-01-02 22.9 20.3 0 10.0
2013-01-03 24.8 18.4 1 28.8
2013-01-04 26.6 18.3 2 33.5
2013-01-05 28.3 20.9 3 33.4
2013-01-06 28.0 21.6 4 32.8
2013-01-07 27.5 21.4 5 26.8
2013-01-08 42.3 20.9 6 25.5
2013-01-09 25.0 21.1 7 20.9
2013-01-10 25.4 20.2 8 14.0
После добавления новых столбцов df1 содержит:
x0 x1 x2 x3 Date max_t1 max_t2 max_t3 min_t1 min_t2 \
0 40 31.05 25.5 25.5 2013-01-03 24.8 26.6 28.3 18.4 18.3
1 35 35.75 36.5 36.5 2013-01-07 27.5 42.3 25.0 21.4 20.9
min_t3 rf1 rf2 rf3 w1 w2 w3
0 20.9 1.0 2.0 3.0 28.8 33.5 33.4
1 21.1 5.0 6.0 7.0 26.8 25.5 20.9
Изменить после "100 дней до"comment
Если добавленные строки следует брать за 100 дней до текущей даты, измените способ установки обеих" дат границы "в функции fn . Что-то вроде:
def fn(row):
d1 = row.Date - pd.Timedelta(nDays, 'D')
d2 = row.Date - pd.Timedelta(1, 'D')
return pd.Series(df2.loc[d1:d2].values.reshape((1, -1), order='F')
.squeeze(), index=cols)
Как избежать увеличения количества строк
Если ваш df2 содержит несколько строк для некоторых дат, тогдаобъединение df1 с df2 приводит к увеличению числа выходных строк.
Если df2 имеет для некоторой даты, например, 3 строки, то для одна строка из df1 с этой датой результат будет содержать всего 3 строки (с одинаковой датой).
Чтобы избежать этого, вы должны "подавить" эти повторения.
Изначально я думал о df2 = df2.drop_duplicates (...) , но вы писали, что одна строка может содержать один набор значений, другие - другие наборы, поэтому мы не можемпроизвольно оставить одну строку и удалить другую (с той же даты).
Одним из возможных решений этой проблемы является то, что после создания «индекса даты» необходимо:
- группа df2 по индексу (каждая группа будет содержать все строки на определенную дату),
- compute означает каждого столбца (в нем отсутствуют возможные NaN значения),
- сохраните результат обратно в df2 .
Код для этого:
df2 = df2.groupby(level=0).mean()
Тогда вы можете присоединиться (как описано выше), и количество выходных строк не должно увеличиваться.