Sử dụng dữ liệu trong khung dữ liệu gấu trúc để khớp các cột với nhau


18

Tôi có hai pandaskhung dữ liệu ab:

a1   a2   a3   a4   a5   a6   a7
1    3    4    5    3    4    5
0    2    0    3    0    2    1
2    5    6    5    2    1    2

b1   b2   b3   b4   b5   b6   b7
3    5    4    5    1    4    3
0    1    2    3    0    0    2
2    2    1    5    2    6    5

Hai khung dữ liệu chứa chính xác cùng một dữ liệu, nhưng theo một thứ tự khác nhau và với các tên cột khác nhau. Dựa trên các số trong hai khung dữ liệu, tôi muốn có thể khớp từng tên cột avới từng tên cột trong b.

Không dễ dàng như chỉ đơn giản so sánh hàng đầu tiên avới hàng đầu tiên bvì có các giá trị trùng lặp, ví dụ cả hai a4a7có giá trị 5nên không thể khớp chúng ngay lập tức với b2hoặc b4.

Cách tốt nhất để làm việc này là gì?

Câu trả lời:


16

Đây là một cách sử dụng sort_values:

m=df1.T.sort_values(by=[*df1.index]).index
n=df2.T.sort_values(by=[*df2.index]).index
d=dict(zip(m,n))
print(d)

{'a1': 'b5', 'a5': 'b1', 'a2': 'b7', 'a3': 'b6', 'a6': 'b3', 'a7': 'b2', 'a4': 'b4'}

Cảm ơn bạn đã chia sẻ lệnh tốt đẹp Anky, bạn có thể vui lòng giải thích thêm về [*df1.index]một phần xin vui lòng? Sẽ biết ơn bạn, chúc mừng.
RavinderSingh13

1
@ RavinderSingh13 Chắc chắn, sort_values(by=..)lấy một danh sách làm tham số để tôi giải nén chỉ mục vào danh sách ở đây, bạn cũng có thể làm list(df1.index)thay vì [*df1.index]:)
anky

16

Đây là một cách tận dụng numpy broadcasting:

b_cols = b.columns[(a.values == b.T.values[...,None]).all(1).argmax(1)]
dict(zip(a, b_cols))

{'a1': 'b5',
 'a2': 'b7',
 'a3': 'b6',
 'a4': 'b4',
 'a5': 'b1',
 'a6': 'b3',
 'a7': 'b2'}

Một cách tiếp cận tương tự khác (bởi @piR):

a_ = a.to_numpy()
b_ = b.to_numpy()
i, j = np.where((a_[:, None, :] == b_[:, :, None]).all(axis=0))
dict(zip(a.columns[j], b.columns[i]))

{'a1': 'b5',
 'a2': 'b7',
 'a3': 'b6',
 'a4': 'b4',
 'a5': 'b1',
 'a6': 'b3',
 'a7': 'b2'}

1
Tôi bịt mũi trong bài viết của bạn. Hy vọng, bạn không phiền. Hãy thay đổi nó theo ý thích của bạn.
piRSquared

Ngược lại :) Cách tiếp cận đẹp và kiểm tra các tệp dữ liệu lớn, nó cải thiện một chút hiệu suất @piRSquared
yatu

12

Một cách merge

s=df1.T.reset_index().merge(df2.T.assign(match=lambda x : x.index))
dict(zip(s['index'],s['match']))
{'a1': 'b5', 'a2': 'b7', 'a3': 'b6', 'a4': 'b4', 'a5': 'b1', 'a6': 'b3', 'a7': 'b2'}

Tôi nghĩ rằng tôi chỉ thêm một giải pháp thông minh khác để thấy rằng nó cũng giống như của bạn (-: rất tiếc.
piRSquared

8

hiểu từ điển

Sử dụng một tupletrong các giá trị cột làm khóa có thể băm trong từ điển

d = {(*t,): c for c, t in df2.items()}
{c: d[(*t,)] for c, t in df1.items()}

{'a1': 'b5',
 'a2': 'b7',
 'a3': 'b6',
 'a4': 'b4',
 'a5': 'b1',
 'a6': 'b3',
 'a7': 'b2'}

Chỉ trong trường hợp chúng tôi không có đại diện hoàn hảo, tôi chỉ sản xuất từ ​​điển cho các cột có khớp.

d2 = {(*t,): c for c, t in df2.items()}
d1 = {(*t,): c for c, t in df1.items()}

{d1[c]: d2[c] for c in {*d1} & {*d2}}

{'a5': 'b1',
 'a2': 'b7',
 'a7': 'b2',
 'a6': 'b3',
 'a3': 'b6',
 'a1': 'b5',
 'a4': 'b4'}

idxmax

Điều này giáp với điều phi lý ... Đừng thực sự làm điều này.

{c: df2.T.eq(df1[c]).sum(1).idxmax() for c in df1}

{'a1': 'b5',
 'a2': 'b7',
 'a3': 'b6',
 'a4': 'b4',
 'a5': 'b1',
 'a6': 'b3',
 'a7': 'b2'}

1
Làm thế nào mà tôi có thể hiểu từng biểu hiện trong các tuyên bố này, nhưng chưa thấy đầy đủ trong đầu những gì đang thực sự ở đây? Giống như cờ vua, tôi biết làm thế nào để di chuyển tất cả các quân cờ trên bảng, nhưng không thể thấy nhiều hơn 2 di chuyển về phía trước.
Scott Boston

Được rồi ... Tôi đã tiêu hóa điều này bây giờ và nó hoàn toàn đơn giản, tuyệt vời. +1
Scott Boston
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.