我有一个 Pandas 数据框,我想调用一个 API 并从该数据框传递一些参数。然后我从 API 获取结果并从中创建一个新列。这是我的工作代码:
import http.client, urllib.request, urllib.parse, urllib.error, base64
import pandas as pd
import json
headers = {
# Request headers
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-Key': 'my-api-key-goes-here',
}
params = urllib.parse.urlencode({
})
df = pd.read_csv('mydata.csv',names=['id','text'])
def call_api(row):
try:
body = {
"documents": [
{
"language": "en",
"id": row['id'],
"text": row['text']
}
]
}
conn = http.client.HTTPSConnection('api-url')
conn.request("POST", "api-endpoint" % params, str(body), headers)
response = conn.getresponse()
data = response.read()
data = json.loads(data)
return data['documents'][0]['score']
conn.close()
except Exception as e:
print("[Errno {0}] {1}".format(e.errno, e.strerror))
df['score'] = df.apply(call_api,axis=1)
上面的效果很好。但是,我对可以执行的 api 请求的数量有限制,API 允许我在同一请求中发送最多 100 个文档,方法是在 body['documents']
列表中添加更多文档。
返回的数据遵循这个模式:
{
"documents": [
{
"score": 0.92,
"id": "1"
},
{
"score": 0.85,
"id": "2"
},
{
"score": 0.34,
"id": "3"
}
],
"errors": null
}
因此,我正在寻找的是不是逐行应用相同的 api 调用,而是每次以 100 行为一组。有什么方法可以在 Pandas 中执行此操作,还是我应该迭代数据框行,自己创建批处理,然后再次迭代以将返回值添加到新列?
请您参考如下方法:
DataFrame.apply()
很慢;我们可以做得更好。这将一次性创建“文档”字典列表:
df.to_dict('records')
然后您需要做的就是将其分成 100 个 block :
start = 0
while start < len(df):
documents = df.iloc[start:start+100].to_dict('records')
call_api(documents)
start += 100
最后,您可以将单个 HTTP session 与 requests
库一起使用:
import requests
session = requests.Session()
call_api(session, documents)
然后在 call_api()
中执行 session.post(...)
。这比每次都建立一个新连接更有效率。