Как я могу получить строки фрейма данных, которые соответствуют диапазонам другого фрейма данных? Например:
import pandas as pd
df1 = pd.DataFrame({
'date': [
pd.Timestamp(2019,1,1),
pd.Timestamp(2019,1,2),
pd.Timestamp(2019,1,3),
pd.Timestamp(2019,2,1),
pd.Timestamp(2019,2,5)
]
})
df2 = pd.DataFrame({
'from_date': [pd.Timestamp(2019,1,1), pd.Timestamp(2019,2,1)],
'to_date': [pd.Timestamp(2019,1,2), pd.Timestamp(2019,2,1)]
})
Данные:
> df1
date
0 2019-01-01 <- I want this
1 2019-01-02 <- and this
2 2019-01-03
3 2019-02-01 <- and this
4 2019-02-05
> df2
from_date to_date
0 2019-01-01 2019-01-02
1 2019-02-01 2019-02-01
Диапазоны могут перекрывать друг друга. Я хочу найти все строки в df1
, которые попадают между Любые диапазонов в df2
. Я старался:
df1[df1['date'].between(df2['from_date'], df2['to_date'])]
Но это привело к ошибке:
ValueError: Can only compare identically-labeled Series objects
Я использую numpy
трансляцию
s2_1=df2.from_date.values
s2_2=df2.to_date.values
s1=df1.values[:,None]
df1[np.any((s1>=s2_1)&(s1<=s2_2),-1)]
Out[35]:
date
0 2019-01-01
1 2019-01-02
3 2019-02-01
@MikeHenderson docs.scipy.org/doc/numpy/user/basics.broadcasting.html, проверьте это
@MikeHenderson также, это больше похоже на цикл for, например [df2.from_date.values<x for x in df1.values ]
, если это все еще не ясно, просто дайте мне знать :-)
@MikeHenderson также вы можете проверить здесь stackoverflow.com/questions/37867354/…
Спасибо, у меня есть несколько нерешенных вопросов о правиле вещания в Numpy, но это материал для другого вопроса SO.
Вот еще один подход:
1) Создайте массив дат, используя понимание списка, numpy.hstack
и pandas.date_range
.
2) Простой логическое индексирование на df1
с использованием этого массива дат и Series.isin
# step 1
dates = np.hstack([pd.date_range(s, e) for s, e in zip(df2['from_date'], df2['to_date'])])
# Step 2
df1[df1.date.isin(dates)]
date
0 2019-01-01
1 2019-01-02
3 2019-02-01
Другой способ, который не рекомендуется для больших фреймов данных, — создать декартово произведение и отфильтровать результаты:
import pandas as pd
df1 = pd.DataFrame({
'date': [
pd.Timestamp(2019,1,1),
pd.Timestamp(2019,1,2),
pd.Timestamp(2019,1,3),
pd.Timestamp(2019,2,1),
pd.Timestamp(2019,2,5)
]
})
df2 = pd.DataFrame({
'from_date': [pd.Timestamp(2019,1,1), pd.Timestamp(2019,2,1)],
'to_date': [pd.Timestamp(2019,1,2), pd.Timestamp(2019,2,1)]
})
df1 = df1.apply(pd.to_datetime)
df2 = df2.apply(pd.to_datetime)
df_out = df1.assign(key=1).merge(df2.assign(key=1))\
.query('from_date <= date <= to_date')
df_out
Выход:
date key from_date to_date
0 2019-01-01 1 2019-01-01 2019-01-02
2 2019-01-02 1 2019-01-01 2019-01-02
7 2019-02-01 1 2019-02-01 2019-02-01
Можете ли вы объяснить, как работает вещание в этом случае?
s1
— это массив длины 5, аs2_1
иs2_2
— массивы длины 2.