Предположим, у меня есть два кадра данных (обратите внимание на индексы столбцов):
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
Я хочу слить их в dataframe, где они будут на своих индексных местах, а остальные заполнены ничем, например:
Каков наилучший (питоновский) способ сделать это?
Эти кадры данных были созданы с помощью следующего кода:
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.
посмотри здесь pandas.pydata.org/docs/reference/api/pandas.concat.html
@quest Спасибо за ваше предложение, я думал, что кода генерации будет достаточно. Также добавлены текстовые варианты.
вы можете использовать pd.concat, а также учитывать ignore_index в concat.
@grumpyp, Sadow, я прочитал документы, но до сих пор не могу понять это.
Вот способ сделать то, что вы просили:
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] для поиска подхода с максимальным индексом! И ваше обновление для меня тоже открывает глаза.
Рад, что это помогло. Подход переиндексации(), предложенный в других ответах, является хорошим. Я обновил свой ответ вариантом, который не полагается на то, что B имеет большую метку максимального столбца, чем A.
Давайте сделаем 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
У нас был примерно такой же подход ;)
Вы можете 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
Пожалуйста, используйте текст вместо изображений. Помогает копировать пасту и быстро реагировать. Спасибо