Создание двух новых фреймов данных из двух существующих фреймов данных с учетом всех комбинаций их многоиндексных столбцов и их значений

#python #pandas #dataframe #combinatorics

Вопрос:

Я хочу создать два новых фрейма данных из двух существующих фреймов данных с учетом всех комбинаций их многоиндексных столбцов и их значений.

 left = pd.DataFrame(([1,0,1], [1,0,0],[1,0,1],), columns=pd.MultiIndex.from_tuples([('A', 'B'), ('A', 'C' ), ('D','D'),]))
right = pd.DataFrame(([8,9], [8,9],[8,9],), columns=pd.MultiIndex.from_tuples([('S', 'T'), ('Y', 'Z'),]))
 
слева:
    A  A  D
   B  C  D
0  1  0  1
1  1  0  0
2  1  0  1
 
правильно:
    S  Y
   T  Z
0  8  9
1  8  9
2  8  9
 
ожидаемый результат
left_result:
    A  A  A  A  D  D
   B  B  C  C  D  D
0  1  1  0  0  1  1
1  1  1  0  0  0  0
2  1  1  0  0  1  1
 
right_result:
    S  Y  S  Y  S  Y
   T  Z  T  Z  T  Z
0  8  9  8  9  8  9
1  8  9  8  9  8  9
2  8  9  8  9  8  9
 

PS: Извините, если мой вопрос недостаточно точен, но пример с ожидаемым результатом по-прежнему объясняет это лучше всего без слов. Возможно, вопрос уже задавался, но в отсутствие точного описания того, какого результата я на самом деле хочу (комбинация в двух фреймах данных?), Я прошу вас помочь сформулировать вопрос более точно или связать его как дубликат, если присутствует существующий вопрос.

Ответ №1:

Мы можем использовать MultiIndex.from_product на основе плоского индекса каждого фрейма данных, а затем reindex на основе соответствующих значений уровня:

 midx = pd.MultiIndex.from_product([left.columns.to_flat_index(),
                                   right.columns.to_flat_index()])

left = left.reindex(columns=midx.get_level_values(0))
right = right.reindex(columns=midx.get_level_values(1))
 

left :

    A           D   
   B  B  C  C  D  D
0  1  1  0  0  1  1
1  1  1  0  0  0  0
2  1  1  0  0  1  1
 

right :

    S  Y  S  Y  S  Y
   T  Z  T  Z  T  Z
0  8  9  8  9  8  9
1  8  9  8  9  8  9
2  8  9  8  9  8  9
 

midx для справки:

 MultiIndex([(('A', 'B'), ('S', 'T')),
            (('A', 'B'), ('Y', 'Z')),
            (('A', 'C'), ('S', 'T')),
            (('A', 'C'), ('Y', 'Z')),
            (('D', 'D'), ('S', 'T')),
            (('D', 'D'), ('Y', 'Z'))],
           )
 

Примечание: уровень 0 — это значения left плоского индекса, а уровень 1 — значения right плоского индекса.

Ответ №2:

Используйте DataFrame.reindex Index.repeat для столбцов ( axis=1 )

 # repeat 'left' columns 2 times 
>>> left = left.reindex(left.columns.repeat(2), axis=1)
>>> left

   A           D   
   B  B  C  C  D  D
0  1  1  0  0  1  1
1  1  1  0  0  0  0
2  1  1  0  0  1  1

# repeat 'right' columns 3 times 
>>> right = right.reindex(right.columns.repeat(3), axis=1)
>>> right 

   S        Y      
   T  T  T  Z  Z  Z
0  8  8  8  9  9  9
1  8  8  8  9  9  9
2  8  8  8  9  9  9
 

Или pandas.concat

 # concatenate 'right' 3 times side by side (axis=1)
>>> right = pd.concat([right]*3, axis=1)
>>> right

   S  Y  S  Y  S  Y
   T  Z  T  Z  T  Z
0  8  9  8  9  8  9
1  8  9  8  9  8  9
2  8  9  8  9  8  9