2017-07-26 21 views
14

Giả sử tôi có hai dataframes d1d2interweave hai dataframes

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 

một cách dễ dàng và tổng quát để interweave cột hai dataframes' là gì. Chúng tôi có thể giả định rằng số cột trong d2 luôn nhỏ hơn một số cột trong d1. Và, các chỉ số là như nhau.

Tôi muốn điều này:

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 

Trả lời

12

Sử dụng pd.concat để kết hợp các DataFrames, và toolz.interleave sắp xếp lại các cột:

from toolz import interleave 

pd.concat([d1, d2], axis=1)[list(interleave([d1, d2]))] 

Sản lượng kết quả được như mong đợi:

0 3 1 4 2 
a 1 0 1 0 1 
b 1 0 1 0 1 
c 1 0 1 0 1 
+0

Rực rỡ như mọi khi ...Tôi đã bắt đầu sử dụng 'cytoolz' trên đề xuất của bạn (-: – piRSquared

+0

Câu trả lời này gần như cảm thấy như gian lận, vì hàm' interleave' được thiết kế riêng cho hoạt động đang được đề cập. Yeah, tôi là một fan hâm mộ lớn 'toolz' /' Tôi nhớ được hạnh phúc khi nhìn thấy bạn sử dụng 'cytoolz' trong một trong những câu hỏi của bạn một chút trong khi trở lại! – root

+0

Sử dụng nó đã https://stackoverflow.com/a/45453058/2336654 – piRSquared

5

interweave các cột:

c = np.empty((d1.columns.size + d2.columns.size,), dtype=object) 
c[0::2], c[1::2] = d1.columns, d2.columns 

Bây giờ, làm một tham gia và đặt hàng lại với boolean lập chỉ mục:

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 

Bạn có thể thích pd.concat khi giao dịch với nhiều dataframes.

1

viết một hàm để trừu tượng đi chung merge-sắp xếp lại

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 
6

Đây là một trong số các phương thức của NumPy h -

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 

mẫu chạy -

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 
1

chúng ta có thể sử dụng 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 
1

Giải pháp của tôi là sử dụng pd.DataFrame.insert đảm bảo để chèn từ phía sau đầu tiên

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 
1

Công thức lặp đi lặp lại roundrobin có một đặc điểm xen kẽ. Tùy chọn này cung cấp sự lựa chọn giữa trực tiếp thực hiện các công thức nấu ăn từ Python docs, hoặc nhập một gói của bên thứ ba như more_itertools mà thực hiện các công thức dành cho bạn:

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 

Lấy cảm hứng từ câu trả lời @ gốc của, các chỉ số cột được xen kẽ và được sử dụng để cắt một DataFrame ghép nối.

Các vấn đề liên quan