#python #python-3.x #pandas #dataframe
Вопрос:
У меня есть 2 кадра данных, и я хочу проверить, находятся ли начальные и конечные диапазоны в DF1 в пределах начальных и конечных диапазонов в DF2, а для тех, которые верны, я хочу распечатать идентификатор и регион. Я хочу сравнить каждую строку DF1 с каждой строкой DF2.
Это мои фреймы данных:
DF1 = pd.DataFrame ({'Start':[500, 850, 1000],
'End':[700, 950, 1200],
'Region':["A", "B", "C"]})
DF2 = pd.DataFrame ({'Start':[200, 800, 1100],
'End':[750, 950, 1250],
'ID':[1, 2, 3]})
DF1
Начать | Конец | Регион |
---|---|---|
500 | 700 | A |
850 | 950 | B |
1000 | 1200 | C |
1100 | 1500 | D |
DF2
Начать | Конец | ID |
---|---|---|
200 | 750 | 1 |
800 | 950 | 2 |
1100 | 1250 | 3 |
Я предполагаю, что мне нужно написать цикл for, чтобы выполнить итерацию по всем строкам. Тем не менее, я новичок, и мне трудно правильно настроить его.
Это код, который я пробовал до сих пор.
for Start, End in DF1:
if Start>=DF2["Start"] and End<=DF2["End"]:
print (DF1["Region"], DF2["ID"])
Однако я получаю эту ошибку: ошибка значения: слишком много значений для распаковки (ожидается 2)
Любые советы о том, как решить эту проблему, будут весьма признательны.
Комментарии:
1. Пожалуйста, сделайте это полностью работающим сценарием, чтобы ответы можно было проверить. Инициализируйте DF1 и т. Д.
2. Вы просто сопоставляете каждую строку DF1 с одной и той же строкой в DF2, или каждый регион сравнивается с каждым идентификатором в DF2?
3. Я хочу проверить каждую строку DF1 на все строки DF2.
4. @pythonbeginner Тогда мое решение с перекрестным соединением должно соответствовать вашим требованиям.
5. @pythonbeginner Есть вопросы по решению ? Не стесняйтесь, дайте мне знать, если вам понадобятся какие-либо разъяснения.
Ответ №1:
Вы можете скрестить 2 .merge()
кадра данных, а затем использовать .query()
для фильтрации строк с требуемым условием, следующим образом:
DF_out = DF1.merge(DF2, how='cross').query('(Start_x >= Start_y) amp; (End_x <= End_y)')
Если ваша версия Pandas старше 1.2.0 (версия от декабря 2020 года) и не поддерживает how='cross'
, вы можете использовать:
DF_out = DF1.assign(key=1).merge(DF2.assign(key=1), on='key').drop('key', axis=1).query('(Start_x >= Start_y) amp; (End_x <= End_y)')
Результат:
Start_x
, End_x
являются оригинальными Start
, End
столбцы в DF1
Start_y
, End_y
являются оригинальными Start
, End
столбцы в DF2
print(DF_out)
Start_x End_x Region Start_y End_y ID
0 500 700 A 200 750 1
4 850 950 B 800 950 2
Затем вы можете легко распечатать Region
и ID
, например
print(DF_out['Region'])
0 A
4 B
Name: Region, dtype: object
print(DF_out['ID'])
0 1
4 2
Name: ID, dtype: int64
Если ваши критерии проверки строго <
или >
, а не <=
или >=
, вы можете изменить символы оператора сравнения в .query()
, следующим образом:
DF_out = DF1.merge(DF2, how='cross').query('(Start_x > Start_y) amp; (End_x < End_y)')
Результат:
print(DF_out)
Start_x End_x Region Start_y End_y ID
0 500 700 A 200 750 1
Комментарии:
1. @pythonbeginner Поскольку вам нужно проверить каждую строку DF1 на все строки DF2, вам неизбежно нужно выполнить некоторую аналогичную операцию, такую как перекрестное соединение. Как насчет того, чтобы разбить мои коды на 2 шага? То есть, получите результат
.merge()
в промежуточном кадре данных, а затем выполните фильтрацию с.query()
помощью отдельного шага. Попробуй.2. К сожалению, его разрыв также приводит к сбою Google colab. Я пытаюсь понять, как увеличить объем оперативной памяти.
3. @pythonbeginner Попробуйте разделить свои фреймы данных на небольшие фрагменты, запустите и объедините результаты. Например
DF1
, разделите их на 4 части, каждая размером около 20000×3. Запустите коды 4 раза каждый с помощью одной из 4 разделенных частей. Что-то вроде того.4. @pythonbeginner Вы уже нашли способ решить проблему с сбоем Google colab ? Недавно я нашел способ значительно ускорить процесс, а также снизить требования к хранению памяти. Посмотрим, не захотите ли вы попробовать мое новое решение. Дайте мне знать, если захотите.