Переплетение двух данных
Предположим, что у меня есть два кадра данных d1
и d2
d1 = pd.DataFrame(np.ones((3, 3), dtype=int), list('abc'), [0, 1, 2])
d2 = pd.DataFrame(np.zeros((3, 2), dtype=int), list('abc'), [3, 4])
d1
0 1 2
a 1 1 1
b 1 1 1
c 1 1 1
d2
3 4
a 0 0
b 0 0
c 0 0
Что такое простой и обобщенный способ переплетения двух столбцов данных. Мы можем предположить, что число столбцов в d2
всегда на единицу меньше числа столбцов в d1
. И, индексы одинаковы.
Я хочу это:
pd.concat([d1[0], d2[3], d1[1], d2[4], d1[2]], axis=1)
0 3 1 4 2
a 1 0 1 0 1
b 1 0 1 0 1
c 1 0 1 0 1
Ответы
Ответ 1
Используя pd.concat
, чтобы объединить DataFrames и toolz.interleave
изменить порядок столбцов:
from toolz import interleave
pd.concat([d1, d2], axis=1)[list(interleave([d1, d2]))]
Полученный результат будет таким, как ожидалось:
0 3 1 4 2
a 1 0 1 0 1
b 1 0 1 0 1
c 1 0 1 0 1
Ответ 2
Здесь один подход NumPy -
def numpy_interweave(d1, d2):
c1 = list(d1.columns)
c2 = list(d2.columns)
N = (len(c1)+len(c2))
cols = [None]*N
cols[::2] = c1
cols[1::2] = c2
out_dtype = np.result_type(d1.values.dtype, d2.values.dtype)
out = np.empty((d1.shape[0],N),dtype=out_dtype)
out[:,::2] = d1.values
out[:,1::2] = d2.values
df_out = pd.DataFrame(out, columns=cols, index=d1.index)
return df_out
Пример прогона -
In [346]: d1
Out[346]:
x y z
a 6 7 4
b 3 5 6
c 4 6 2
In [347]: d2
Out[347]:
p q
a 4 2
b 7 7
c 7 2
In [348]: numpy_interweave(d1, d2)
Out[348]:
x p y q z
a 6 4 7 2 4
b 3 7 5 7 6
c 4 7 6 2 2
Ответ 3
Переплетаем столбцы:
c = np.empty((d1.columns.size + d2.columns.size,), dtype=object)
c[0::2], c[1::2] = d1.columns, d2.columns
Теперь выполните объединение и переупорядочение с булевским индексированием:
d1.join(d2)[c]
0 3 1 4 2
a 1 0 1 0 1
b 1 0 1 0 1
c 1 0 1 0 1
Вы можете предпочесть pd.concat
при работе с несколькими фреймами данных.
Ответ 4
написать функцию, чтобы абстрагировать общий слияние-реорганизацию
from itertools import zip_longest
def weave(df1, df2):
col1 = df1.columns
col2 = df2.columns
weaved = [col for zipped in zip_longest(col1,col2)
for col in zipped
if col is not None]
return pd.concat([df1, df2], axis=1)[weaved]
weave(d1, d2)
# Output:
0 3 1 4 2
a 1 0 1 0 1
b 1 0 1 0 1
c 1 0 1 0 1
Ответ 5
мы можем использовать itertools.zip_longest:
In [75]: from itertools import zip_longest
In [76]: cols = pd.Series(np.concatenate(list(zip_longest(d1.columns, d2.columns)))).dropna()
In [77]: cols
Out[77]:
0 0
1 3
2 1
3 4
4 2
dtype: object
In [78]: df = pd.concat([d1, d2], axis=1)[cols]
In [79]: df
Out[79]:
0 3 1 4 2
a 1 0 1 0 1
b 1 0 1 0 1
c 1 0 1 0 1
Ответ 6
Мое решение состояло в том, чтобы использовать pd.DataFrame.insert
, чтобы убедиться, что он вставлен с первого раза
df = d1.copy()
for i in range(d2.shape[1], 0, -1):
df.insert(i, d2.columns[i - 1], d2.iloc[:, i - 1])
df
0 3 1 4 2
a 1 0 1 0 1
b 1 0 1 0 1
c 1 0 1 0 1
Ответ 7
Рецепт roundrobin
itertools имеет характеристику перемежения. Этот вариант предлагает выбор между непосредственным внедрением рецепта из Python docs или импортом стороннего пакета, такого как more_itertools
, который реализует вам рецепт:
from more_itertools import roundrobin
pd.concat([d1, d2], axis=1)[list(roundrobin(d1, d2))]
# Output
0 3 1 4 2
a 1 0 1 0 1
b 1 0 1 0 1
c 1 0 1 0 1
Вдохновленный @root ответом, индексы столбца чередуются и используются для среза конкатенированного DataFrame.