首页 > 解决方案 > Python Pandas 中的嵌套循环 - 将子循环结果组合成连接的 df,并在文件名中使用组名保存

问题描述

我有一个看起来像下面的示例的 df。我正在尝试按组运行一个循环:

对于正确设置循环的示例,实际查询 API 的合适替代方法是将一些文本和 DESC 打印为新 .csv 中的新行。

我已经勾勒出我认为循环在 Python 和普通语言的混合中看起来像什么(在大写字母中带有 * *)。

我通常是 R 用户,但需要使用 Python 进行 API 查询。如何将下面的草图或大纲翻译成工作 Python?

import pandas as pd
data = [[1,1,'ab'],[1,2,'bc'],[1,3,'de'],[2,1,'gh'],[2,2,'hi'],[2,3,'jk'],[3,1,'kl'],[3,2,'lm']]
df = pd.DataFrame(data,columns=['id1','id2','DESCR'])
df_gp = df.groupby(id1)
for name, group in df_gp: 
    for i in range(1, len(*WHAT_HERE_ID2?*)): 
        result[i] = *PRINT(DESCR) OR SOMETHING JUST TO CREATE A SAMPLE OBJECT_to be replaced w/API code*
        result[i] = pd.DataFrame(result[i])
    filename = 'myfileprefix_' + df_gp.loc[name] + '.csv'
    all = *how to CONCATENATE result[i] through result[max(id2)] into one df*    
    all.to_csv(filename)

注意:我需要单独执行每个 id2 API 查询的全部原因是 b/c 如果我将所有 id2 作为一个组提交给 id1 的一个查询,它有时会超过查询限制(例如,如果多个 id2 返回大# 记录,它超过了查询限制,但是当我一次做一个 id2 时,这永远不会发生)。

结果应该是 3 个名为 .csv 的文件:

里面包含所有 id2 查询的结果。

标签: pythonpandasloopsnested

解决方案


iterrows您可以在分组的 DataFrame 内迭代行:

# a function to be replaced with actual API call
def mock_api_call(v):
    return f'api output for {v}'

# iterate over groups by `id1`
for id1, g in df_gp:

    # iterate over rows inside each group
    for i, r in g.iterrows():
        g.loc[i, 'result'] = mock_api_call(r['DESCR'])

    fn = f'myfileprefix{id1}.csv'
    g.to_csv(fn)

myfileprefix1.csv例如,中的输出将是:

   id1  id2 DESCR             result
0    1    1    ab  api output for ab
1    1    2    bc  api output for bc
2    1    3    de  api output for de

PS 作为一个稍微不那么冗长的选项,您也可以使用apply代替iterrows

for id1, g in df_gp:
    g['result'] = g['DESCR'].apply(mock_api_call)
    fn = f'myfileprefix{id1}.csv'
    g.to_csv(fn)

更新:根据您对 API 调用返回 DataFrame 的说明:

for id1, g in df_gp:
    # set up DataFrame to collect all API responses for the group
    dfg = pd.DataFrame()
    
    # iterate over rows inside each group
    for i, r in g.iterrows():
        # get DataFrame from API call
        dfi = mock_api_call(r['DESCR'])
        
        # if needed, add columns to API response DataFrame, e.g.
        # dfi['DESCR'] = r['DESCR']
        # ...
        
        # concatenate new results to dfg
        dfg = pd.concat([dfg, dfi], ignore_index=True)

    fn = f'myfileprefix{id1}.csv'
    dfg.to_csv(fn)

推荐阅读