Stata/Python 集成第 6 部分:使用 API 和 JSON 数据

 

 

引言

数据无处不在。许多政府机构、金融机构、大学和社交媒体平台通过应用程序接口(API)提供对其数据的访问。API 通常以 JavaScript 对象表示法(JSON)文件的形式返回所请求的数据。在这篇文章中,我将向您展示如何使用 Python 通过 API 调用请求数据,以及如何处理生成的 JSON 数据。

如果您不熟悉 Python,在继续阅读之前,阅读我的 Stata/Python 集成系列的前四篇文章可能会有所帮助:

 

API 和 JSON 数据

API 是一种软件应用程序,可用于从另一个计算系统请求数据。有许多不同类型的 API,语法通常对每个 API 都是唯一的。但典型的 API 由 URL 和查询选项组成。例如,下面的 URL 使用 openFDA API 从美国食品药品监督管理局请求关于不良药物事件的数据。

https://api.fda.gov/drug/event.json?

我们可以向我们的 API 调用添加选项来缩小我们的数据请求范围。例如,下面的 URL 请求 2018 年 1 月 1 日至 2018 年 1 月 5 日期间美国发生的涉及芬太尼的不良事件数量。

https://api.fda.gov/drug/event.json?search=receivedate [20180101+TO+20180105]+AND+occurcountry:"US" +AND+patient.drug.openfda.brand_name:"Fentanyl"&count=receivedate

我们可以在 Web 浏览器的地址栏中输入此 API 调用的 URL,浏览器将显示结果数据作为 JSON 文件。

浏览器显示 JSON 数据

JSON 是一种流行的数据文件格式,由一系列 键:值 对组成。"键"类似于 Stata 数据集中的变量,"值"是数据。上图底部附近包含 键:值 对 time:"20180105"。键是 time,值是 "20180105"。

JSON 数据通常是嵌套的。例如,time:"20180105" 嵌套在 4: 键中。在上图中,time: 键嵌套在 4: 键中,而 4: 键嵌套在 results: 键中。JSON 嵌套结构的顶部有两个键:meta: 和 results:。

我们的目标是使用 openFDA API 请求关于不良药物事件的数据,并将嵌套的 JSON 数据转换为 Stata 数据集。我们将使用 requests 和 pandas 包,所以在开始之前,您应该检查它们是否已安装。

 

定义 API 调用的 URL

让我们首先在 Python 代码块中定义一个名为 URL 的字符串。字符串 URL 包含使用 openFDA API 请求不良事件数据的 URL。

python:
URL = 'https://api.fda.gov/drug/event.json'
URL
end

上面代码块第三行中的语句 URL 显示字符串 URL 的内容。

. python:
---------------------------------------- python (type end to exit) -------------
>>> URL = 'https://api.fda.gov/drug/event.json'
>>> URL
'https://api.fda.gov/drug/event.json'

>>> end
--------------------------------------------------------------------------------

我们可以通过向 API 调用添加搜索字段和值来自定义我们的数据请求。您可以在 openFDA 网站上查看语法、可搜索字段列表和示例。

让我们通过在下面的代码块中向 API 调用添加 ?search 选项,将搜索限制在 2018 年 1 月 1 日至 2018 年 1 月 5 日期间报告的不良事件。

python:
URL = 'https://api.fda.gov/drug/event.json
> ?search=receivedate:[20180101+TO+20180105]'
URL
end

语法有效,但我们只添加了一个搜索字段,API 调用的 URL 已经很难阅读。让我们将 URL 分成两个字符串:API 和 date。字符串 API 包含基本 API 调用的 URL,字符串 date 将我们的搜索范围缩小到 2018 年 1 月 1 日至 2018 年 1 月 5 日。然后,我们可以通过输入 URL = API + date 来组合字符串。

python:
API = 'https://api.fda.gov/drug/event.json?search='
date = 'receivedate:[20180101+TO+20180105]'
URL = API + date
URL
end

我们的 Python 代码块更容易阅读,API 调用的 URL 仍然相同。

. python:
-------------------------------------------- python (type end to exit) --------
>>> API = 'https://api.fda.gov/drug/event.json?search='
>>> date = 'receivedate:[20180101+TO+20180105]'
>>> URL = API + date
>>> URL
'https://api.fda.gov/drug/event.json?search=receivedate:[20180101+TO+20180105]'
>>> end
-------------------------------------------------------------------------------

让我们进一步将查询限制在 2018 年 1 月 1 日至 2018 年 1 月 5 日期间在美国发生的不良事件。在下面的代码块中,字符串 country 包含将查询限制在美国的语法。然后,我们可以组合字符串 API、date 和 country 来指定存储在字符串 URL 中的完整 API 调用。请注意,在定义 URL 时,我们必须在 date 和 country 之间包含 "+AND+"。

python:
API = 'https://api.fda.gov/drug/event.json?search='
date = 'receivedate:[20180101+TO+20180105]'
country = 'occurcountry:"US"'
URL = API + date + "+AND+" + country
URL
end

即使我们的 API 调用的 URL 变得更加复杂,我们的代码仍然易于阅读。

. python:
-------------------------------------------- python (type end to exit) --------
>>> API = 'https://api.fda.gov/drug/event.json?search='
>>> date = 'receivedate:[20180101+TO+20180105]'
>>> country = 'occurcountry:"US"'
>>> URL = API + date + "+AND+" + country
>>> URL
'https://api.fda.gov/drug/event.json?search=receivedate:[20180101+TO+20180105]
> +AND+occurcountry:"US"'
>>> end
-------------------------------------------------------------------------------

我们可以使用类似的策略进一步将查询限制在涉及药物芬太尼的不良事件。下面代码块中的字符串 drug 包含指定不良事件涉及芬太尼的语法。

python:
API = 'https://api.fda.gov/drug/event.json?search='
date = 'receivedate:[20180101+TO+20180105]'
country = 'occurcountry:"US"'
drug = 'patient.drug.openfda.brand_name:"Fentanyl"'
URL = API + date + "+AND+" + country + "+AND+" + drug
URL
end

最后,让我们指定我们的结果包含每天发生的不良事件数量。下面代码块中的字符串 data 包含特定的语法,必须添加到 API 调用的 URL 的末尾。请注意,字符串 data 必须以 & 开头,而不是 +AND+。

python:
API = 'https://api.fda.gov/drug/event.json?search='
date = 'receivedate:[20180101+TO+20180105]'
country = 'occurcountry:"US"'
drug = 'patient.drug.openfda.brand_name:"Fentanyl"'
data = 'count=receivedate'
URL = API + date + "+AND+" + country + "+AND+" + drug + "&" + data
URL
end

尽管我们的 API 调用的 URL 变得相当复杂,但我们的代码块仍然易于阅读。

. python:
-------------------------------------------- python (type end to exit) --------
>>> API = 'https://api.fda.gov/drug/event.json?search='
>>> date = 'receivedate:[20180101+TO+20180105]'
>>> country = 'occurcountry:"US"'
>>> drug = 'patient.drug.openfda.brand_name:"Fentanyl"'
>>> data = 'count=receivedate'
>>> URL = API + date + "+AND+" + country + "+AND+" + drug + "&" + data
>>> URL
'https://api.fda.gov/drug/event.json?search=receivedate:[20180101+TO+20180105]
> +AND+occurcountry:"US"+AND+patient.drug.openfda.brand_name:"Fentanyl"
> &count=receivedate'
>>> end
-------------------------------------------------------------------------------

 

使用 API 调用请求数据

现在,我们准备将我们的 API 调用提交给 openFDA 数据服务器。让我们首先导入 requests 包。我们可以使用 get() 方法提交我们的 API 调用的 URL。然后,我们将生成的 JSON 数据存储在一个名为 data 的字典对象中。

python:
import requests

API = 'https://api.fda.gov/drug/event.json?search='
date = 'receivedate:[20180101+TO+20180105]'
country = 'occurcountry:"US"'
drug = 'patient.drug.openfda.brand_name:"Fentanyl"'
data = 'count=receivedate'
URL = API + date + "+AND+" + country + "+AND+" + drug + "&" + data
data = requests.get(URL).json()
data
end

我们可以通过输入 data 来查看 data 对象的内容,就像上面代码块中那样。下面输出中显示的数据很难阅读,因为它们尚未格式化用于显示。

. python:
-------------------------------------------- python (type end to exit) --------
>>> import requests
>>> API = 'https://api.fda.gov/drug/event.json?search='
>>> date = 'receivedate:[20180101+TO+20180105]'
>>> country = 'occurcountry:"US"'
>>> drug = 'patient.drug.openfda.brand_name:"Fentanyl"'
>>> data = 'count=receivedate'
>>> URL = API + date + "+AND+" + country + "+AND+" + drug + "&" + data
>>> data = requests.get(URL).json()
>>> data
{'meta': {'disclaimer': 'Do not rely on openFDA to make decisions regarding
> medical care. While we make every effort to ensure that data is accurate, you
> should assume all results are unvalidated. We may limit or otherwise restrict
> your access to the API in line with our Terms of Service.', 'terms':
> 'https://open.fda.gov/terms/', 'license': 'https://open.fda.gov/license/',
> 'last_updated': '2020-09-09'}, 'results': [{'time': '20180101', 'count': 1},
> {'time': '20180102', 'count': 16}, {'time': '20180103', 'count': 20},
> {'time': '20180104', 'count': 25}, {'time': '20180105', 'count': 24}]}
>>> end
-------------------------------------------------------------------------------

我们可以使用 json 模块以更易读的格式显示数据。让我们首先在下面的代码块中导入 json 模块。然后,我们可以使用 dumps() 方法对 JSON 数据进行编码。indent=4 选项以缩进方式显示每一级嵌套的数据。sort_keys=True 选项对数据进行排序。print() 告诉 Python 显示 dumps() 方法的结果。

python:
import requests
import json
API = 'https://api.fda.gov/drug/event.json?search='
date = 'receivedate:[20180101+TO+20180105]'
country = 'occurcountry:"US"'
drug = 'patient.drug.openfda.brand_name:"Fentanyl"'
data = 'count=receivedate'
URL = API + date + "+AND+" + country + "+AND+" + drug + "&" + data
data = requests.get(URL).json()
print(json.dumps(data, indent=4, sort_keys=True))
end

下面输出中的数据更容易阅读。我们现在可以看到数据嵌套在 meta 和 results 键中。meta 键包含免责声明、数据最后更新的日期、许可证 URL 和使用条款。这是有用的信息,但我不想将其包含在我的数据集中。我只想使用存储在 results 键中的数据。

. python:
-------------------------------------------- python (type end to exit) --------
>>> import requests
>>> import json
>>> API = 'https://api.fda.gov/drug/event.json?search='
>>> date = 'receivedate:[20180101+TO+20180105]'
>>> country = 'occurcountry:"US"'
>>> drug = 'patient.drug.openfda.brand_name:"Fentanyl"'
>>> data = 'count=receivedate'
>>> URL = API + date + "+AND+" + country + "+AND+" + drug + "&" + data
>>> data = requests.get(URL).json()
>>> print(json.dumps(data, indent=4, sort_keys=True))
{
"meta": {
"disclaimer": "Do not rely on openFDA to make decisions regarding
> medical care. While we make every effort to ensure that data is accurate,
> you should assume all results are unvalidated. We may limit or otherwise
> restrict your access to the API in line with our Terms of Service.",
"last_updated": "2020-09-09",
"license": "https://open.fda.gov/license/",
"terms": "https://open.fda.gov/terms/"
},
"results": [
{
"count": 1,
"time": "20180101"
},
{
"count": 16,
"time": "20180102"
},
{
"count": 20,
"time": "20180103"
},
{
"count": 25,
"time": "20180104"
},
{
"count": 24,
"time": "20180105"
}
]
}
>>> end
-------------------------------------------------------------------------------

将 JSON 数据转换为 Stata 数据集

我们可以使用 get() 方法提取 data 对象的 results 部分,并将其放在一个名为 fdadata 的列表对象中。

python:
import requests
import json
API = 'https://api.fda.gov/drug/event.json?search='
date = 'receivedate:[20180101+TO+20180105]'
country = 'occurcountry:"US"'
drug = 'patient.drug.openfda.brand_name:"Fentanyl"'
data = 'count=receivedate'
URL = API + date + "+AND+" + country + "+AND+" + drug + "&" + data
data = requests.get(URL).json()
fdadata = data.get('results', [])
print(json.dumps(fdadata, indent=4, sort_keys=True))
end

我们可以通过查看下面的输出来验证我们是否成功提取了数据。

. python:
-------------------------------------------- python (type end to exit) --------
>>> import requests
>>> import json
>>> API = 'https://api.fda.gov/drug/event.json?search='
>>> date = 'receivedate:[20180101+TO+20180105]'
>>> country = 'occurcountry:"US"'
>>> drug = 'patient.drug.openfda.brand_name:"Fentanyl"'
>>> data = 'count=receivedate'
>>> URL = API + date + "+AND+" + country + "+AND+" + drug + "&" + data
>>> data = requests.get(URL).json()
>>> fdadata = data.get('results', [])
>>> print(json.dumps(fdadata, indent=4, sort_keys=True))
[
{
"count": 1,
"time": "20180101"
},
{
"count": 16,
"time": "20180102"
},
{
"count": 20,
"time": "20180103"
},
{
"count": 25,
"time": "20180104"
},
{
"count": 24,
"time": "20180105"
}
]

>>> end
-------------------------------------------------------------------------------

fdadata 列表对象中的数据仍然是"键:值"格式,我想将它们转换为 pandas 数据框的"行和列"格式。让我们首先使用别名 pd 导入 pandas 模块。然后,我们可以使用 read_json() 方法将 fdadata 列表对象读入一个名为 fda_df 的 pandas 数据框中。

python:
import requests
import json
import pandas as pd
API = 'https://api.fda.gov/drug/event.json?search='
date = 'receivedate:[20180101+TO+20180105]'
country = 'occurcountry:"US"'
drug = 'patient.drug.openfda.brand_name:"Fentanyl"'
data = 'count=receivedate'
URL = API + date + "+AND+" + country + "+AND+" + drug + "&" + data
data = requests.get(URL).json()
fdadata = data.get('results', [])
fda_df = pd.read_json(json.dumps(fdadata))
fda_df
end

下面输出中显示的数据框 fda_df 包含五行三列。第一列是数据框的索引。第二列名为"time",包含每个观察的日期。第三列名为"count",包含美国在该日期发生的涉及芬太尼的不良事件数量。

. python:
-------------------------------------------- python (type end to exit) --------
>>> import requests
>>> import json
>>> import pandas as pd
>>> API = 'https://api.fda.gov/drug/event.json?search='
>>> date = 'receivedate:[20180101+TO+20180105]'
>>> country = 'occurcountry:"US"'
>>> drug = 'patient.drug.openfda.brand_name:"Fentanyl"'
>>> data = 'count=receivedate'
>>> URL = API + date + "+AND+" + country + "+AND+" + drug + "&" + data
>>> data = requests.get(URL).json()
>>> fdadata = data.get('results', [])
>>> fda_df = pd.read_json(json.dumps(fdadata))
>>> fda_df
time count
0 20180101 1
1 20180102 16
2 20180103 20
3 20180104 25
4 20180105 24

>>> end
-------------------------------------------------------------------------------

现在,我们可以使用 to_stata() 方法将 pandas 数据框 fda_df 保存到一个名为 fentanyl.dta 的 Stata 数据集中。version=118 选项指定数据将以 Stata 16 数据文件格式存储。

python:
import requests
import json
import pandas as pd
API = 'https://api.fda.gov/drug/event.json?search='
date = 'receivedate:[20180101+TO+20180105]'
country = 'occurcountry:"US"'
drug = 'patient.drug.openfda.brand_name:"Fentanyl"'
data = 'count=receivedate'
URL = API + date + "+AND+" + country + "+AND+" + drug + "&" + data
data = requests.get(URL).json()
fdadata = data.get('results', [])
fda_df = pd.read_json(json.dumps(fdadata))
fda_df.to_stata('fentanyl.dta', version=118)
end

我们可以列出 Stata 数据文件 fentanyl.dta 的内容,以验证数据是否已正确保存。

. use fentanyl.dta, clear

. list

+--------------------------+
| index time count |
|--------------------------|
1. | 0 20180101 1 |
2. | 1 20180102 16 |
3. | 2 20180103 20 |
4. | 3 20180104 25 |
5. | 4 20180105 24 |
+--------------------------+

此时,将我们的 API 调用中的日期范围扩展到 2010 年 1 月 1 日至 2020 年 1 月 1 日,并绘制结果数据(见下面的代码块)将很容易。

芬太尼不良事件趋势图

结论

我们做到了!我们成功地向 openFDA 提交了 API 调用,处理了生成的 JSON 数据,并将 JSON 数据转换为 Stata 数据集。您可能对向 FDA 报告的不良药物事件不感兴趣。但您可以使用类似的步骤下载和处理对您有用的各种数据。只需在搜索引擎中输入"popular api data",准备好大吃一惊。每个 API 都有其自己独特的搜索字段和语法,因此您需要阅读文档。但您的耐心和坚持将为您带来一个充满数据的世界。

我在下面收集了代码并添加了注释,以提醒您每组 Python 语句的目的。

example.do

python:
# 导入包
import requests
import json
import pandas as pd

# 构建API调用的URL
API = 'https://api.fda.gov/drug/event.json?search='
date = 'receivedate:[20100101+TO+20200101]'
country = 'occurcountry:"US"'
drug = 'patient.drug.openfda.brand_name:"Fentanyl"'
data = 'count=receivedate'
URL = API + date + "+AND+" + country + "+AND+" + drug + "&" + data

# 提交API数据请求
data = requests.get(URL).json()

# 提取JSON数据的'results'部分
fdadata = data.get('results', [])

# 将JSON数据转换为pandas数据框
fda_df = pd.read_json(json.dumps(fdadata))

# 使用pandas将数据框写入Stata 16数据集
fda_df.to_stata('fentanyl.dta', version=118)

end

use fentanyl.dta, clear
drop index
generate date = mofd(date(string(time, "%8.0f"),"YMD"))
format date %tm
collapse (sum) count, by(date)
tsset date, monthly

twoway (line count date, lcolor(blue) lwidth(medthick)), \\
ytitle("Adverse Events Reported to the FDA") \\
ylabel(0(2000)8000, angle(horizontal) grid) \\
xtitle("") \\
title("Fentanyl Adverse Events Reported to the FDA") \\
caption(Data Source: openFDA, size(small)) \\
scheme(s1color)

 

 

 

 

 


 

在线留言

尊敬的客户朋友,如您有任何意见建议,请通过下表反馈给我们,我们会尽快与您联系。

 

 

 

 

联系我们

 

微信公众号

咨询微信

企业店铺

400-621-1085

(节假日期间办公室座机如无人接听,请选择其他联系方式,感谢理解!祝您节日快乐!)

 

联系我们 快速链接 相关产品 上海卡贝信息技术有限公司

©2025  上海卡贝信息技术有限公司

产品中心

下载中心

站点地图

隐私政策

 

销售QQ咨询

产品QQ咨询

淘宝店铺

IBM SPSS Statistics 20 -统计分析软件
IBM SPSS Statistics 31 -统计分析软件

 

综述

功能概述

Stata/MP

最新更新:19版

版本选择

 

EQS

GraphPad Prism

LISREL

SmarPLS

Statgraphics

HLM

IRTPRO

flexMIRT

IBM SPSS Statistics

SAS

NCSS

PASS

SigmaPlot

nQuery

Analyse-it

MedCalc

AMOS

GAUSS

SYSTAT

EViews