这是我在论坛上的第一个问题。感谢您的帮助!
我基于df.iterrows()(sic。)编写了嵌套的for循环,执行该过程需要花费大量时间。我需要通过在描述的条件下检查所有单元格来将值从一个数据帧转换为另一个数据帧。您能帮我使它生效吗? (多重处理,应用方法,向量化还是其他?) 会非常感激! :)
样本数据:
import pandas as pd
import numpy as np
d1 = {'geno_start' : [60, 1120, 1660], 'geno_end' : [90, 1150, 1690], 'original_subseq' : ['AAATGCCTGAACCTTGGAATTGGA', 'AAATGCCTGAACCTTGGAATTGGA', 'AAATGCCTGAACCTTGGAATTGGA']}
d2 = {'most_left_coordinate_genome' : [56, 1120, 1655], 'most_right_coordinate_genome' : [88, 1150, 1690], 'protein_ID' : ['XYZ_1', 'XYZ_2', 'XYZ_3']}
df_1 = pd.DataFrame(data=d1)
df_2 = pd.DataFrame(data=d2)
df_1['protein_ID'] = np.nan
def match_ranges(df1: pd.DataFrame, df2: pd.DataFrame):
for index, row_2 in df2.iterrows():
for index_1, row_1 in df1.iterrows():
if (row_1['geno_start'] >= row_2['most_left_coordinate_genome']) & (row_1['geno_end'] <= row_2['most_right_coordinate_genome']):
df1['protein_ID'].iloc[index_1] = row_2['protein_ID']
elif (abs(row_1['geno_start'] - row_2['most_left_coordinate_genome']) < 30) & (row_1['geno_end'] <= row_2['most_right_coordinate_genome']):
df1['protein_ID'].iloc[index_1] = row_2['protein_ID']
elif (row_1['geno_start'] >= row_2['most_left_coordinate_genome']) & (abs(row_1['geno_end'] - row_2['most_right_coordinate_genome']) < 30):
df1['protein_ID'].iloc[index_1] = row_2['protein_ID']
match_ranges(df_1, df_2)
答案 0 :(得分:0)
这是从2个for循环到1个循环的一种方式。我重命名了几列以减少行宽。
首先,创建数据框:
import pandas as pd
d1 = {'geno_start' : [60, 1120, 1660],
'geno_end' : [90, 1150, 1690],
'original_subseq' : ['AAATGCCTGAACCTTGGAATTGGA',
'AAATGCCTGAACCTTGGAATTGGA',
'AAATGCCTGAACCTTGGAATTGGA'],}
d2 = {'left' : [56, 1120, 1655],
'right' : [88, 1150, 1690],
'protein_ID' : ['XYZ_1', 'XYZ_2', 'XYZ_3']}
df_1 = pd.DataFrame(data=d1)
df_1['protein_ID'] = '?'
df_1['rule'] = '?'
df_2 = pd.DataFrame(data=d2)
第二,在第一个数据框中填充protein_ID
列(即,以基因组开始,基因组结束):
for g in df_1.itertuples():
# Rule A: left most <= geno start < geno end <= right-most
# LM-----------------------RM left- and right-most
# GS-----------GE genome start, end
if ((df_2['left'] <= g.geno_start) & (g.geno_end <= df_2['right'])).any():
mask = (df_2['left'] <= g.geno_start) & (g.geno_end <= df_2['right'])
df_1.at[g.Index, 'protein_ID'] = df_2.loc[mask, 'protein_ID'].values[0]
df_1.at[g.Index, 'rule'] = 'Rule A'
# Rule B: geno start before left-most
# LM-----------------RM
# GS-----------------GE
elif ((df_2['left'] - g.geno_start < 30) & (g.geno_end <= df_2['right'])).any():
mask = (df_2['left'] - g.geno_start < 30) & (g.geno_end <= df_2['right'])
df_1.at[g.Index, 'protein_ID'] = df_2.loc[mask, 'protein_ID'].values[0]
df_1.at[g.Index, 'rule'] = 'Rule B'
# Rule C: geno end after right-most
# LM-----------------RM
# GS-----------------GE
elif ((df_2['left'] <= g.geno_start) & (g.geno_end - df_2['right'] < 30)).any():
mask = (df_2['left'] <= g.geno_start) & (g.geno_end - df_2['right'] < 30)
df_1.at[g.Index, 'protein_ID'] = df_2.loc[mask, 'protein_ID'].values[0]
df_1.at[g.Index, 'rule'] = 'Rule C'
else:
pass
print(df_1)
geno_start geno_end original_subseq protein_ID rule
0 60 90 AAATGCCTGAACCTTGGAATTGGA XYZ_1 Rule C
1 1120 1150 AAATGCCTGAACCTTGGAATTGGA XYZ_2 Rule A
2 1660 1690 AAATGCCTGAACCTTGGAATTGGA XYZ_3 Rule A