Объедините или соедините два набора данных, используя между двумя числами в python

#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