Переплетение двух данных

Предположим, что у меня есть два кадра данных 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.