Выберите строки, которые попадают между диапазонами, определенными в другом DataFrame

Как я могу получить строки фрейма данных, которые соответствуют диапазонам другого фрейма данных? Например:

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
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
4
0
85
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

Я использую 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

Можете ли вы объяснить, как работает вещание в этом случае? s1 — это массив длины 5, а s2_1 и s2_2 — массивы длины 2.

Mike Henderson 19.04.2019 04:39

@MikeHenderson docs.scipy.org/doc/numpy/user/basics.broadcasting.html, проверьте это

BENY 19.04.2019 04:41

@MikeHenderson также, это больше похоже на цикл for, например [df2.from_date.values<x for x in df1.values ], если это все еще не ясно, просто дайте мне знать :-)

BENY 19.04.2019 04:43

@MikeHenderson также вы можете проверить здесь stackoverflow.com/questions/37867354/…

BENY 19.04.2019 04:56

Спасибо, у меня есть несколько нерешенных вопросов о правиле вещания в Numpy, но это материал для другого вопроса SO.

Mike Henderson 19.04.2019 20:55

Вот еще один подход:

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

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