如何编写一个迭代 pandas 数据框组并应用分层条件的函数?
How to write a function that iterates over groups of pandas dataframe and applies hierarchical conditions?
我需要编写一个函数来根据某些分层条件过滤数据集。该函数的目的是为一堆蛋白质中的每个蛋白质获得一个注释。
函数需要做的事情如下,
- 按“id”列对蛋白质进行分组
- 检查蛋白质组中的每个分析
- 按优先顺序选择分析(这不是排序问题,因此应按条件顺序给出分析,以便稍后可以重新排序)。首先,检查 analysis_1 如果它不存在然后取 analysis_2 或 analysis_3,等等
- 将行放入新的数据框中。
这是将被过滤的数据示例,
df=pd.DataFrame({
'id': ['Protein_1', 'Protein_1', 'Protein_1',
'Protein_2','Protein_2','Protein_2'],
'analysis': ['analysis_6', 'analysis_4', 'analysis_1',
'analysis_3','analysis_2','analysis_5'],
'annotation':['annotation_1', 'annotation_2', 'annotation_3',
'annotation_1','annotation_2','annotation_3'] })
这是我希望看到的输出,
df_filtered= pd.DataFrame({
'id': ['Protein_1','Protein_2'],
'analysis': ['analysis_1', 'analysis_2'],
'annotation':['annotation_3', 'annotation_2'] })
下面的代码可以正常工作,但我想使用 pandas groupby、apply 和 iterrows 函数来实现。
new_df =pd.DataFrame(columns=df.columns)
protein_id=list(df.id.unique())
for protein in protein_id:
data=df[df["id"] == protein]
if len(data[data["analysis"] =="analysis_1"]) == 0:
if len(data[data["analysis"] =="analysis_2"]) == 0:
if len(data[data["analysis"] =="analysis_3"]) == 0:
pass
else:
data2=data[data["analysis"] =="analysis_3"]
new_df = pd.concat([new_df,data2])
else:
data2=data[data["analysis"] =="analysis_2"]
new_df = pd.concat([new_df,data2])
else:
data2=data[data["analysis"] =="analysis_1"]
new_df = pd.concat([new_df,data2])
new_df
感谢任何帮助!!
您可以使用矢量化方法来执行此操作,如果 analysis
列遵循相同的模式,您可以按 _
拆分并获得最后一个整数层次结构:
方法一:(如果每组可以有重复的最小层级)
helper_s = df['analysis'].str.split("_").str[-1].astype(int)
out = df[helper_s.eq((df.assign(helper_s=helper_s)
.groupby("id")['helper_s'].transform("min")))]
id analysis annotation
2 Protein_1 analysis_1 annotation_3
4 Protein_2 analysis_2 annotation_2
方法二:
helper_s = df['analysis'].str.split("_").str[-1].astype(int)
out = df.loc[df.assign(helper_s=helper_s).groupby("id")['helper_s'].idxmin()]
id analysis annotation
2 Protein_1 analysis_1 annotation_3
4 Protein_2 analysis_2 annotation_2
您可以临时 对数据框进行排序,然后为每个 ID 删除除一个条目之外的所有条目。它看起来像这样:
df.sort_values('analysis').drop_duplicates(['id'], keep='first')
请注意,这不会更改原始数据框中的顺序。结果如下所示:
id analysis annotation
2 Protein_1 analysis_1 annotation_3
4 Protein_2 analysis_2 annotation_2
如果你有一个returns分析优先级的函数,你可以结合上面的方法使用它:
def prio_function(analysis):
# return a low number for a better result
# and a high number for a worse result
return int(analysis.split('_')[1]) # replace this row by your code
df_work= df.assign(_prio=df['analysis'].apply(prio_function))
df_work.sort_values('_prio').drop_duplicates(['id'], keep='first').drop(columns='_prio')
如果优先排序更简单,您也可以将字典传递给 apply
而不是函数。
我需要编写一个函数来根据某些分层条件过滤数据集。该函数的目的是为一堆蛋白质中的每个蛋白质获得一个注释。
函数需要做的事情如下,
- 按“id”列对蛋白质进行分组
- 检查蛋白质组中的每个分析
- 按优先顺序选择分析(这不是排序问题,因此应按条件顺序给出分析,以便稍后可以重新排序)。首先,检查 analysis_1 如果它不存在然后取 analysis_2 或 analysis_3,等等
- 将行放入新的数据框中。
这是将被过滤的数据示例,
df=pd.DataFrame({
'id': ['Protein_1', 'Protein_1', 'Protein_1',
'Protein_2','Protein_2','Protein_2'],
'analysis': ['analysis_6', 'analysis_4', 'analysis_1',
'analysis_3','analysis_2','analysis_5'],
'annotation':['annotation_1', 'annotation_2', 'annotation_3',
'annotation_1','annotation_2','annotation_3'] })
这是我希望看到的输出,
df_filtered= pd.DataFrame({
'id': ['Protein_1','Protein_2'],
'analysis': ['analysis_1', 'analysis_2'],
'annotation':['annotation_3', 'annotation_2'] })
下面的代码可以正常工作,但我想使用 pandas groupby、apply 和 iterrows 函数来实现。
new_df =pd.DataFrame(columns=df.columns)
protein_id=list(df.id.unique())
for protein in protein_id:
data=df[df["id"] == protein]
if len(data[data["analysis"] =="analysis_1"]) == 0:
if len(data[data["analysis"] =="analysis_2"]) == 0:
if len(data[data["analysis"] =="analysis_3"]) == 0:
pass
else:
data2=data[data["analysis"] =="analysis_3"]
new_df = pd.concat([new_df,data2])
else:
data2=data[data["analysis"] =="analysis_2"]
new_df = pd.concat([new_df,data2])
else:
data2=data[data["analysis"] =="analysis_1"]
new_df = pd.concat([new_df,data2])
new_df
感谢任何帮助!!
您可以使用矢量化方法来执行此操作,如果 analysis
列遵循相同的模式,您可以按 _
拆分并获得最后一个整数层次结构:
方法一:(如果每组可以有重复的最小层级)
helper_s = df['analysis'].str.split("_").str[-1].astype(int)
out = df[helper_s.eq((df.assign(helper_s=helper_s)
.groupby("id")['helper_s'].transform("min")))]
id analysis annotation
2 Protein_1 analysis_1 annotation_3
4 Protein_2 analysis_2 annotation_2
方法二:
helper_s = df['analysis'].str.split("_").str[-1].astype(int)
out = df.loc[df.assign(helper_s=helper_s).groupby("id")['helper_s'].idxmin()]
id analysis annotation
2 Protein_1 analysis_1 annotation_3
4 Protein_2 analysis_2 annotation_2
您可以临时 对数据框进行排序,然后为每个 ID 删除除一个条目之外的所有条目。它看起来像这样:
df.sort_values('analysis').drop_duplicates(['id'], keep='first')
请注意,这不会更改原始数据框中的顺序。结果如下所示:
id analysis annotation
2 Protein_1 analysis_1 annotation_3
4 Protein_2 analysis_2 annotation_2
如果你有一个returns分析优先级的函数,你可以结合上面的方法使用它:
def prio_function(analysis):
# return a low number for a better result
# and a high number for a worse result
return int(analysis.split('_')[1]) # replace this row by your code
df_work= df.assign(_prio=df['analysis'].apply(prio_function))
df_work.sort_values('_prio').drop_duplicates(['id'], keep='first').drop(columns='_prio')
如果优先排序更简单,您也可以将字典传递给 apply
而不是函数。