#python #pandas #merge
Вопрос:
У меня есть два набора данных;
Попытка объединить df2 (данные содержимого) с df1 (просмотренные данные). Придется использовать слияние. Однако ключ не является стандартным, но должен быть промежуточным ключом.
df1 = pd.DataFrame({"ID": [1, 2],"start":[7200, 1000],"end":[7400, 1100],"duration":[200, 100]})
df2 = pd.DataFrame({"Prog_start":[7100,7300,980,1050],"Prog_end":[7300,7400,1050,1150],"Prog":["Prog_1","Prog_2","Prog_3","Prog_4"]})
desired_output=pd.DataFrame({"ID":[1,1,2,2],"start":[7200,7200,1000,1000],"end":[7400,7400,1100,1100],"duration":[200,200,100,100],"Prog_start":[7100,7300,980,1050],"Prog_end":[7300,7400,1050,1150],"Prog":["Prog_1","Prog_2","Prog_3","Prog_4"],"Dur_Prog":[100,100,20,50]})
Я пробовал использовать iloc и между функциями, которые не работают.
Комментарии:
1. Не могли бы вы, пожалуйста, объяснить логику слияния?
2. Я получил данные о посещаемости включения программы и выключения программы. Это время начала и время окончания программы. В другом наборе данных я получил, какие программы были воспроизведены за то время, которое люди просматривали.
Ответ №1:
Вы можете взять декартово произведение df1
и df2
, затем отфильтровать только перекрывающиеся интервалы и рассчитать длительность:
# cartesian product and interval filtering
z = (df1
.assign(k=1).merge(df2.assign(k=1), on='k')
.query('(Prog_start < end) amp; (Prog_end > start)')
.drop(columns='k'))
# duration calculation
z['Duration_Prog'] = (np.clip(z['Prog_end'], z['start'], z['end']) -
np.clip(z['Prog_start'], z['start'], z['end']))
z
Выход:
ID start end duration Prog_start Prog_end Prog Duration_Prog
0 1 7200 7400 200 7100 7300 Prog_1 100
1 1 7200 7400 200 7300 7400 Prog_2 100
6 2 1000 1100 100 980 1050 Prog_3 50
7 2 1000 1100 100 1050 1150 Prog_4 50
P.S. Есть ли ошибка в вашей строке 3 desired_output
? Так и должно быть Duration_Prog = 50
, если я правильно понимаю логику (перекрытие есть 1000 - 1050
)
P. P. S. И с более новой pandas
версией (1.2.0 ), которую вы можете использовать merge
how='cross'
для декартового соединения, нет необходимости во временном k
столбце
Комментарии:
1. ты прав. Произошла ошибка. Предполагается, что их должно быть 50 в ряд. Логика, о которой вы упомянули, выглядит идеальной. Однако я получаю сообщение об ошибке: «Вы пытаетесь объединить столбцы int64 и object. Если вы хотите продолжить, вам следует использовать pd.concat». Я посмотрел на типы Dtypes. Оба столбца в обоих наборах данных имеют значение int64
2. Вероятно, у вас есть какие-то другие столбцы,
df1
иdf2
тогда они перекрываются. Попробуйте установитьon='k'
вmerge
:.assign(k=1).merge(df2.assign(k=1), on='k')
3. Обновил это в своем ответе
4. ДА. Теперь это сработало. Спасибо. Это сработало как заклинание. Я постараюсь разобраться в том, как=»перекрестное» соединение.
5. Превосходно! Re
how='cross'
, вы можете просто сделатьdf1.merge(df2, how='cross')
это, и вам это не понадобитсяdrop(columns='k')
позже, поэтому он более лаконичен, но он работает только сpandas
версией 1.2.0