Как объединить DataFrames в индексы своих столбцов?

Предположим, у меня есть два кадра данных (обратите внимание на индексы столбцов):

enter image description here = А =

        2   3   4
    0   A1  A1  A1
    1   A2  A2  A2
    2   A3  A3  A3
    3   A4  A4  A4
    4   A5  A5  A5

enter image description here = В =

    6   7   8   9
0   B1  B1  B1  B1
1   B2  B2  B2  B2
2   B3  B3  B3  B3
3   B4  B4  B4  B4
4   B5  B5  B5  B5

Я хочу слить их в dataframe, где они будут на своих индексных местах, а остальные заполнены ничем, например:

enter image description here

Каков наилучший (питоновский) способ сделать это?

Эти кадры данных были созданы с помощью следующего кода:

import pandas as pd
df = pd.DataFrame(columns = range(10))
A = ['A' + str(i) for i in range(1, 6)]
B = ['B' + str(i) for i in range(1, 6)]
df[[2,3,4]] = list(zip(A, A, A))
df[[6,7,8,9]] = list(zip(B, B, B, B))
df.fillna('', inplace = True)   # Output dataframe
df.drop(columns = [0, 1] + list(range(5, 10)))   # A dataframe
df.drop(columns = list(range(0, 6)))    # B dataframe 

УПД Я благодарю всех участников, это было очень проницательно. reindex кажется, самый элегантный способ сделать это. Тем не менее, Constantstranger в конце концов предоставил самое продуманное обновление, а также показал удобный способ хранить меньший DataFrame внутри непустого большого DataFrame, в соответствии с его индексами столбцов, что также ценно для меня. Так что, как бы сложно ни было выбрать лучший ответ, я выбираю его.

Для тех, кто будет бороться с подобной задачей, я могу добавить, что fill_value = '' во время переиндексации поможет избавиться от надоедливых NaN.

Пожалуйста, используйте текст вместо изображений. Помогает копировать пасту и быстро реагировать. Спасибо

quest 17.05.2022 13:08

посмотри здесь pandas.pydata.org/docs/reference/api/pandas.concat.html

grumpyp 17.05.2022 13:08

@quest Спасибо за ваше предложение, я думал, что кода генерации будет достаточно. Также добавлены текстовые варианты.

Artyrm Sergeev 17.05.2022 13:19

вы можете использовать pd.concat, а также учитывать ignore_index в concat.

Sadcow 17.05.2022 13:20

@grumpyp, Sadow, я прочитал документы, но до сих пор не могу понять это.

Artyrm Sergeev 17.05.2022 13:27
Анализ настроения постов в Twitter с помощью Python, Tweepy и Flair
Анализ настроения постов в Twitter с помощью Python, Tweepy и Flair
Анализ настроения текстовых сообщений может быть настолько сложным или простым, насколько вы его сделаете. Как и в любом ML-проекте, вы можете выбрать...
7 лайфхаков для начинающих Python-программистов
7 лайфхаков для начинающих Python-программистов
В этой статье мы расскажем о хитростях и советах по Python, которые должны быть известны разработчику Python.
Установка Apache Cassandra на Mac OS
Установка Apache Cassandra на Mac OS
Это краткое руководство по установке Apache Cassandra.
Сертификатная программа "Кванты Python": Бэктестер ансамблевых методов на основе ООП
Сертификатная программа "Кванты Python": Бэктестер ансамблевых методов на основе ООП
В одном из недавних постов я рассказал о том, как я использую навыки количественных исследований, которые я совершенствую в рамках программы TPQ...
Создание персонального файлового хранилища
Создание персонального файлового хранилища
Вы когда-нибудь хотели поделиться с кем-то файлом, но он содержал конфиденциальную информацию? Многие думают, что электронная почта безопасна, но это...
Создание приборной панели для анализа данных на GCP - часть I
Создание приборной панели для анализа данных на GCP - часть I
Недавно я столкнулся с интересной бизнес-задачей - визуализацией сбоев в цепочке поставок лекарств, которую могут просматривать врачи и...
1
5
44
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вот способ сделать то, что вы просили:

import pandas as pd
import numpy as np

A = pd.DataFrame(data={j: ['A' + str(i) for i in range(1, 6)] for j in range(2, 5)})
B = pd.DataFrame(data={j: ['B' + str(i) for i in range(1, 6)] for j in range(6, 10)})
print(A)
print(B)

newColumns = range(1 + max(A.columns[-1], B.columns[-1]))
df = pd.DataFrame({newCol: [np.nan] * max(len(A.index), len(B.index)) for newCol in newColumns})
df[A.columns] = A
df[B.columns] = B
print(df)

Выход:

    2   3   4
0  A1  A1  A1
1  A2  A2  A2
2  A3  A3  A3
3  A4  A4  A4
4  A5  A5  A5
    6   7   8   9
0  B1  B1  B1  B1
1  B2  B2  B2  B2
2  B3  B3  B3  B3
3  B4  B4  B4  B4
4  B5  B5  B5  B5
    0   1   2   3   4   5   6   7   8   9
0 NaN NaN  A1  A1  A1 NaN  B1  B1  B1  B1
1 NaN NaN  A2  A2  A2 NaN  B2  B2  B2  B2
2 NaN NaN  A3  A3  A3 NaN  B3  B3  B3  B3
3 NaN NaN  A4  A4  A4 NaN  B4  B4  B4  B4
4 NaN NaN  A5  A5  A5 NaN  B5  B5  B5  B5

Если вы предпочитаете значение заполнения, отличное от NaN (например, пустая строка), вы можете изменить это при инициализации df.

Обновлено:

Альтернатива строкам = A и = B выше:

df[list(A.columns) + list(B.columns)] = pd.concat([A, B], axis=1)

ОБНОВЛЕНИЕ №2:

Ответы Ohter (от @mozway и @Shubham Sharma) предложили использовать reindex(), что элегантно. Я просто хотел бы отметить, что, чтобы быть более общим, переиндексация, вероятно, должна использовать максимальную метку столбца A и B (вместо того, чтобы полагаться на то, что она больше):

df = pd.concat([A, B], axis = 1).reindex(range(max(A.columns[-1], B.columns[-1]) + 1), axis = 'columns')

Большое тебе спасибо. Каким бы ни был лучший ответ, это было очень поучительно для меня. Например, ваши однострочники для поколений A и B и A.columns[-1] для поиска подхода с максимальным индексом! И ваше обновление для меня тоже открывает глаза.

Artyrm Sergeev 17.05.2022 13:51

Рад, что это помогло. Подход переиндексации(), предложенный в других ответах, является хорошим. Я обновил свой ответ вариантом, который не полагается на то, что B имеет большую метку максимального столбца, чем A.

constantstranger 17.05.2022 14:04

Давайте сделаем reindex после join

C = A.join(B)
C = C.reindex(range(C.columns.max() + 1), axis=1)

    0   1   2   3   4   5   6   7   8   9
0 NaN NaN  A1  A1  A1 NaN  B1  B1  B1  B1
1 NaN NaN  A2  A2  A2 NaN  B2  B2  B2  B2
2 NaN NaN  A3  A3  A3 NaN  B3  B3  B3  B3
3 NaN NaN  A4  A4  A4 NaN  B4  B4  B4  B4
4 NaN NaN  A5  A5  A5 NaN  B5  B5  B5  B5

У нас был примерно такой же подход ;)

mozway 17.05.2022 13:44

Вы можете concat и reindex:

out = pd.concat([A, B], axis=1).reindex(columns=range(B.columns.max()+1))

или, если вы не знаете, на каком входе находится максимальное количество столбцов (python ≥ 3.8):

out = (d:=pd.concat([A, B], axis=1)).reindex(columns=range(d.columns.max()+1))

выход:

    0   1   2   3   4   5   6   7   8   9
0 NaN NaN  A1  A1  A1 NaN  B1  B1  B1  B1
1 NaN NaN  A2  A2  A2 NaN  B2  B2  B2  B2
2 NaN NaN  A3  A3  A3 NaN  B3  B3  B3  B3
3 NaN NaN  A4  A4  A4 NaN  B4  B4  B4  B4
4 NaN NaN  A5  A5  A5 NaN  B5  B5  B5  B5

Другие вопросы по теме