Панды, создающие фрейм данных с повторяющимся столбцом

#python #pandas #dataframe

#python #pandas #фрейм данных

Вопрос:

Имея два приведенных ниже вектора, я пытаюсь получить желаемый результат без цикла for.

 re = [1,2]
po = [1, 3, 5, 10, 20]
 

Желаемый результат:

 re  po
1   1
1   3
1   5
1   10
1   20
2   1
2   3
2   5
2   10
2   20
 

Любая помощь приветствуется.

Ответ №1:

Вы можете использовать itertools.product и конструктор фрейма данных:

 re = [1,2]
po = [1, 3, 5, 10, 20]

from itertools import product
df = pd.DataFrame(product(re, po), columns=['re', 'po'])
 

Вы также можете использовать pandas.MultiIndex.from_product и преобразовывать to_frame :

 re = [1,2]
po = [1, 3, 5, 10, 20]

df = pd.MultiIndex.from_product([re, po], names=['re', 'po']).to_frame(index=False)
 

Вывод:

    re  po
0   1   1
1   1   3
2   1   5
3   1  10
4   1  20
5   2   1
6   2   3
7   2   5
8   2  10
9   2  20
 

Комментарии:

1. Спасибо за исправления 😉 (набирал с телефона)

Ответ №2:

Вы можете умножить каждый список на длину другого и передать его pd.DataFrame :

 out = pd.DataFrame([re*len(po), po*len(re)], index=['re','po']).T.sort_values(by=['re','po'])
 

Вывод:

    re  po
0   1   1
6   1   3
2   1   5
8   1  10
4   1  20
5   2   1
1   2   3
7   2   5
3   2  10
9   2  20
 

Ответ №3:

Вы можете использовать функцию слияния для выполнения перекрестного слияния. Для этого вы должны сделать каждый вектор фреймом данных, а затем объединить их следующим образом :

 re = [1,2]
po = [1, 3, 5, 10, 20]
reDf = pd.DataFrame({"re":re})
po = pd.DataFrame({"po":po})
repo = re.merge(po,how="cross")
 

Или, если вы не хотите определять новые переменные:

 re = [1,2]
po = [1, 3, 5, 10, 20]
repo = pd.DataFrame({"re":re}).merge(pd.DataFrame({"po":po}), how="cross")
 

Вывод:

    re  po
   1   1
   1   3
   1   5
   1  10
   1  20
   2   1
   2   3
   2   5
   2  10
   2  20
 

Ответ №4:

Одним из вариантов является функция expand_grid из pyjanitor, которая выполняется довольно быстро:

 #pip install pyjanitor
import janitor as jn

others = {'re':re, 'po':po}
jn.expand_grid(others = others).droplevel(1,1)
 
   re  po
0   1   1
1   1   3
2   1   5
3   1  10
4   1  20
5   2   1
6   2   3
7   2   5
8   2  10
9   2  20
 

Ответ №5:

Вы можете использовать понимание списка: output = [[x,y] for x in re for y in po]

Вот полный код.

 import pandas as pd

re = [1,2]
po = [1, 3, 5, 10, 20]

output = [[x,y] for x in re for y in po]

df = pd.DataFrame(output, columns = ['re', 'po'])

display(df)
 

Вывод:

    re  po
0   1   1
1   1   3
2   1   5
3   1  10
4   1  20
5   2   1
6   2   3
7   2   5
8   2  10
9   2  20