遍历API调用的Pandas DataFrame的最快方法

Mar*_*ros 4 python pandas python-requests

我的目标是为Pandas DataFrame中的每一行调用一个API,该API在响应JSON中包含字符串列表,并创建一个新的DataFrame,每个响应一行。我的代码基本上如下所示:

i = 0
new_df = pandas.DataFrame(columns = ['a','b','c','d'])
for index,row in df.iterrows():
    url = 'http://myAPI/'
    d = '{"SomeJSONData:"' + row['data'] + '}'
    j = json.loads(d)
    response = requests.post(url,json = j)

    data = response.json()
    for new_data in data['c']:
        new_df.loc[i] = [row['a'],row['b'],row['c'],new_data]
        i += 1
Run Code Online (Sandbox Code Playgroud)

这可以正常工作,但是我要进行大约5500个API调用,并向新的DataFrame中写入大约6500行,所以这需要一段时间,可能需要10分钟。我想知道是否有人知道一种加快速度的方法?我对在Python中并行运行for循环不太熟悉,可以在保持线程安全性的同时做到这一点吗?

2ya*_*yan 5

也许符合这些思路?这样,您无需创建一个全新的数据框,只声明一次URL,并利用了熊猫列操作比逐行操作更快的事实。

url = 'http://myAPI/'

def request_function(j):
    return requests.post(url,json = json.loads(j))['c'] 

df['j']= '{"SomeJsonData:"' + df['data'] + '}'
df['new_data'] = df['j'].apply(request_function)
Run Code Online (Sandbox Code Playgroud)

现在要证明在这种情况下使用apply(String data)确实要快得多,这是一个简单的测试:

import numpy as np
import pandas as pd
import time

def func(text):
    return text + ' is processed'


def test_one():
    data =pd.DataFrame(columns = ['text'], index = np.arange(0, 100000))
    data['text'] = 'text'

    start = time.time()
    data['text'] = data['text'].apply(func)
    print(time.time() - start)


def test_two():
    data =pd.DataFrame(columns = ['text'], index = np.arange(0, 100000))
    data['text'] = 'text'

    start = time.time()

    for index, row in data.iterrows():
        data.loc[index, 'text'] = row['text'] + ' is processed'

    print(time.time() - start)
Run Code Online (Sandbox Code Playgroud)

对数据帧进行字符串操作的结果。

test_one(使用apply):0.023002147674560547

test_two(使用迭代):18.912891149520874

基本上,通过使用添加两列并应用的内置pandas操作,您应该得到更快的结果,您的响应时间确实受到API响应时间的限制。如果结果仍然太慢,则可能需要考虑编写一个将结果保存到列表的异步函数。然后,您发送并应用该异步功能。

  • @ juanpa.arrivillaga请不要散布错误信息。在幕后,熊猫进行了许多优化。apply函数最终利用了许多内部优化的优势,例如在Cython中使用迭代器。如果您不同意,请尝试自己进行测试。统计数据胜于雄辩。 (2认同)