2015-07-31 35 views
6

Tôi đã tìm kiếm rất nhiều câu trả lời, câu hỏi gần nhất là Compare 2 columns of 2 different pandas dataframes, if the same insert 1 into the other in Python, nhưng câu trả lời cho vấn đề cụ thể của người này là một sự hợp nhất đơn giản. Một cách tổng quát.pandas Python: thay thế giá trị nhiều cột khớp với nhiều cột từ một khung dữ liệu khác

Tôi có hai khung dữ liệu lớn, df1 (thường khoảng 10 triệu hàng) và df2 (khoảng 130 triệu hàng). Tôi cần cập nhật các giá trị trong ba cột của df1 với các giá trị từ ba cột df2, dựa trên hai cột df1 khớp với hai cột df2. Điều bắt buộc là thứ tự của df1 vẫn không thay đổi và chỉ các hàng có giá trị phù hợp mới được cập nhật.

Đây là cách dataframes trông giống như:

df1 

chr snp x pos a1 a2 
1 1-10020 0 10020 G A  
1 1-10056 0 10056 C G  
1 1-10108 0 10108 C G 
1 1-10109 0 10109 C G  
1 1-10139 0 10139 C T 

Lưu ý rằng nó không phải luôn luôn như vậy mà các giá trị của "SNP" là chr-pos, có thể mất nhiều giá trị khác không có liên kết đến bất kỳ các cột (như rs1234, indel-6032 vv)

df2 

ID   CHR STOP OCHR OSTOP 
rs376643643 1 10040  1 10020 
rs373328635 1 10066  1 10056  
rs62651026  1 10208  1 10108  
rs376007522 1 10209  1 10109 
rs368469931 3 30247  1 10139 

tôi cần cập nhật [ 'SNP', 'chr', 'pos'] trong df1 với df2 [[ 'ID', 'OCHR', ' OSTOP ']] chỉ khi df1 [[' chr ',' pos ']] khớp với df2 [[' OCHR ',' OSTOP ']]

như vậy trong trường hợp này, sau khi cập nhật, df1 sẽ trông như thế:

chr  snp x  pos a1 a2  
1 rs376643643 0 10040 G A  
1 rs373328635 0 10066 C G  
1 rs62651026 0 10208 C G  
1 rs376007522 0 10209 C G  
3 rs368469931 0 30247 C T 

Tôi đã sử dụng kết hợp như một cách giải quyết:

df1 = pd.merge(df1, df2, how='left', left_on=["chr", "pos"], right_on=["OCHR", "OSTOP"], 
            left_index=False, right_index=False, sort=False) 

và sau đó

df1.loc[~df1.OCHR.isnull(), ["snp", "chr", "pos"]] = df1.loc[~df1.OCHR.isnull(), ["ID", "CHR", "STOP"]].values 

và sau đó loại bỏ thêm cột. Có, nó hoạt động, nhưng những gì sẽ là một cách để làm điều đó trực tiếp bằng cách so sánh các giá trị từ cả hai dataframes, tôi chỉ không biết làm thế nào để xây dựng nó, và tôi không thể tìm thấy một câu trả lời bất cứ nơi nào; Tôi đoán nó có thể hữu ích để có được một câu trả lời chung về điều này.

Tôi cố gắng đó nhưng nó không hoạt động:

df1.loc[(df1.chr==df2.OCHR) & (df1.pos==df2.OSTOP),["snp", "chr", "pos"]] = df2.loc[df2[['OCHR', 'OSTOP']] == df1.loc[(df1.chr==df2.OCHR) & (df1.pos==df2.OSTOP),["chr", "pos"]],['ID', ''CHR', 'STOP']].values 

Cảm ơn,

Stephane

+1

"Tôi cần phải cập nhật [' snp ',' chr ',' pos '] trong df1 với df2 [[' ID ',' OCHR ',' OSTOP ']] chỉ khi df1 [[' 'chr', 'pos']] khớp với df2 [['OCHR ',' OSTOP ']] "Không phải chỉ nói rằng bạn cần cập nhật' df1.snp' với 'df2.ID' chỉ khi' char' và 'pos' trong df1 khớp' OCHR' và 'OSTOP' trong df2 ? – Alexander

+0

Nếu bạn hợp nhất chr, ochr và pos, ostop, thì không cần cập nhật .. có thể bạn muốn cập nhật chr-> CHR và post-> STOP? – dermen

+0

đây là ví dụ trong ví dụ của bạn, sau khi hợp nhất, bạn muốn cập nhật df1.chr -> df2.CHR và df1.pos -> df2.STOP, có thể đúng nếu đó là lỗi đánh máy – dermen

Trả lời

6

Bạn có thể sử dụng chức năng update (yêu cầu thiết lập các tiêu chí phù hợp để index). Tôi đã sửa đổi dữ liệu mẫu của bạn để cho phép một số dữ liệu không phù hợp.

# your data 
# ===================== 
# df1 pos is modified from 10020 to 10010 
print(df1) 

    chr  snp x pos a1 a2 
0 1 1-10020 0 10010 G A 
1 1 1-10056 0 10056 C G 
2 1 1-10108 0 10108 C G 
3 1 1-10109 0 10109 C G 
4 1 1-10139 0 10139 C T 

print(df2) 

      ID CHR STOP OCHR OSTOP 
0 rs376643643 1 10040  1 10020 
1 rs373328635 1 10066  1 10056 
2 rs62651026 1 10208  1 10108 
3 rs376007522 1 10209  1 10109 
4 rs368469931 3 30247  1 10139 

# processing 
# ========================== 
# set matching columns to multi-level index 
x1 = df1.set_index(['chr', 'pos'])['snp'] 
x2 = df2.set_index(['OCHR', 'OSTOP'])['ID'] 
# call update function, this is inplace 
x1.update(x2) 
# replace the values in original df1 
df1['snp'] = x1.values 
print(df1) 

    chr   snp x pos a1 a2 
0 1  1-10020 0 10010 G A 
1 1 rs373328635 0 10056 C G 
2 1 rs62651026 0 10108 C G 
3 1 rs376007522 0 10109 C G 
4 1 rs368469931 0 10139 C T 
+0

Hi Jianxun, trông rất thú vị, tôi chưa bao giờ sử dụng nhiều chỉ mục. Trong ví dụ bạn chỉ cập nhật cột 'snp', nếu tôi sử dụng x1 = df1.set_index (['chr', 'pos']) ['snp', 'chr', 'pos'] x2 = df2.set_index (['OCHR', 'OSTOP']) ['ID', 'CHR', 'STOP'] sẽ cập nhật tất cả ba cột khi gọi x1.update (x2)? (Tôi không hiểu tại sao không) Cảm ơn rất nhiều. – Stephane

1

Bắt đầu bằng cách renaiming các cột mà bạn muốn kết hợp trong df2

df2.rename(columns={'OCHR':'chr','OSTOP':'pos'},inplace=True) 

Bây giờ merge bằng các cột

df_merged = pd.merge(df1, df2, how='inner', on=['chr', 'pos']) # you might have to preserve the df1 index at this stage, not sure 

Tiếp theo, bạn muốn

updater = df_merged[['D','CHR','STOP']] #this will be your update frame 
updater.rename(columns={'D':'snp','CHR':'chr','STOP':'pos'},inplace=True) # rename columns to update original 

Cuối cùng cập nhật (xem botto m this link):

df1.update(df1_updater) #updates in place 
# chr   snp x pos a1 a2 
#0 1 rs376643643 0 10040 G A 
#1 1 rs373328635 0 10066 C G 
#2 1 rs62651026 0 10208 C G 
#3 1 rs376007522 0 10209 C G 
#4 3 rs368469931 0 30247 C T 

cập nhật hoạt động bằng cách kết hợp index/cột, do đó bạn có thể phải chuỗi dọc theo chỉ số của df1 cho toàn bộ quá trình, sau đó làm df1_updater.re_index(... trước df1.update(df1_updater)

+0

Cảm ơn bạn rất nhiều, tôi rõ ràng là cần phải đọc về chức năng cập nhật, nó xuất hiện rất hữu ích. – Stephane

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