社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

Stata-Python交互:调用APIs和JSON数据

连享会 • 4 月前 • 190 次点击  



👇 连享会 · 推文导航 | www.lianxh.cn

🍓 课程推荐:连享会:2025 寒假班
嘉宾:连玉君(初级|高级);杨海生(前沿)
时间:2025 年 1 月 13-24 日
咨询:王老师 18903405450(微信)



作者: 徐云娇 (厦门大学)
邮箱: jilyo@stu.xmu.edu.cn

致谢: 本文摘自以下文章,特此感谢!
Source: Chuck Huber, The Stata Blog: Stata/Python integration part 6: Working with APIs and JSON data -Link-

温馨提示: 文中链接在微信中无法生效。请点击底部「阅读原文」。或直接长按/扫描如下二维码,直达原文:

Stata/Python 交互系列推文 源自 Stata 公司的统计项目总监 Chuck Huber 博士发表于 Stata 官网的系列博文,一共 9 篇。较为系统地介绍了 Stata 与 Python 的交互方式,包括:如何配置你的软件、如何实现 Stata 与 Python 数据集互通、如何调用 Python 工具包、如何进行机器学习分析等。

  • Part 1: Setting up Stata to use Python -Link-
  • Part 2: Three ways to use Python in Stata -Link-
  • Part 3: How to install Python packages -Link-
  • Part 4: How to use Python packages-Link-
  • Part 5: Three-dimensional surface plots of marginal predictions-Link-
  • Part 6: Working with APIs and JSON data -Link-
  • Part 7: Machine learning with support vector machines, -Link-
  • Part 8: Using the Stata Function Interface to copy data from Stata to Python, -Link-
  • Part 9: Using the Stata Function Interface to copy data from Python to Stata, -Link-

中文编译稿列表如下:

  • Stata-Python交互-9:将python数据导入Stata
  • Stata-Python交互-8:将Stata数据导入Python
  • Stata-Python交互-7:在Stata中实现机器学习-支持向量机
  • Stata-Python交互-6:调用APIs和JSON数据
  • Stata-Python交互-5:边际效应三维立体图示
  • Stata-Python交互-4:如何调用Python宏包
  • Stata-Python交互-3:如何安装Python宏包
  • Stata-Python交互-2:在Stata中调用Python的三种方式
  • Stata-Python交互-1:二者配合的基本设定


目录

  • 1. 引言

  • 2. API 和 JSON

  • 3. 为 API 定义一个 URL

  • 4. 通过 API 指令抓取数据

  • 5. 将 JSON 数据转化为 Stata 数据集

  • 6. 结语

  • 7. 相关推文



1. 引言

在大数据时代,数据无处不在。许多政府部门、金融机构、大学、以及网络平台上都会通过应用程序接口 (Application Programming Interface, API) 提供数据。而 API 通常会将爬取的数据保存为 JSON 文件。

在这篇推文中,我们将展示如何利用 Python 爬取 API 数据、以及如何处理得到的 JSON 数据。

如果你是 Python 新手的话,那建议阅读一下 Stata/Python 深度融合系列的前四篇推文,这也许会对你有帮助。

2. API 和 JSON

API 是一个应用程序接口,它可以为我们抓取平台数据提供诸多便利。API 有许多种类,并且每一个 API 的语法结构都是独一无二的。一个典型的 API 由包含查询选项的 URL 组成,比如美国 「openFDA」  API 的 URL 可以抓取美国药监局关于药品不良事件的数据。

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

可以通过对上述 API 的 URL 添加选项,以达到抓取更精确数据的目的。举个例子,下面的 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

将上面的 URL 输入你的浏览器地址栏中时,浏览器会呈现以下 JSON 格式的数据。

JSON 是一种很受欢迎的数据格式,它包含了一系列的「键值对」,其中 “键” 和 Stata 数据集中的变量很相似,“值” 和 Stata 中的观测值相似。如,{"time" : "20180101"} 中,键就是 "time:" ,而值就是 "20180101"。

JSON 数据通常是嵌套的。如,"time:"、"count:" 键都嵌套在 "results:" 键下,并且 JSON 嵌套格式下最顶端的两个键是 "meta:" 和 "results:"。

我们的目标是利用 「openFDA」 的 API 爬取关于药品不良事件的数据,并且将嵌套的 JSON 数据转化为 Stata 的数据集。

接下来,我们将调入 requests 和 pandas 包,所以需要确认一下 Python 中是否安装这两个包。

3. 为 API 定义一个 URL

首先,用 Python 定义字符串 URL,并将 https://open.fda.gov/ 赋值给 URL

Stata 16 中代码如下:

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」 官网查看相关查询指令的「语法结构」,包括「可检索范围」和「例子」等。

如,我们将搜索的范围限制在 2018 年 1 月 1 日至 2018 年 1 月 5 日间,可以通过添加 ?search 选项来实现。为了提高代码的可读性,我们将 URL 拆分为两个字符串:APIdate。字符串 API 包含了基础 API 指令的 URL 地址,字符串 date 则将搜索范围限制在 2018 年 1 月 1 日至 2018 年 1 月 5 日。之后,我们将两个字符串合并起来即可。

python:
API  = 'https://api.fda.gov/drug/event.json?search='
date = 'receivedate:[20180101+TO+20180105]'
URL  = API + date
URL
end
. 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
--------------------------------------------------

进一步,我们将地区限制在美国。在下例中,字符串 country 将我们的查询地区限制在了美国。之后,我们可以合并字符串 APIdatecountry,将它存储为字符串 URL。这里需要注意,我们必须要在 datecountry 之间加上 “+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 指令变得更加复杂了,但是我们的代码可读性依旧很高。

. 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 可以进一步限制药品不良事件涉及的药品为 Fentanyl。

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 的是 & 而不是 +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
. 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=re
> ceivedate'

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

4. 通过 API 指令抓取数据

现在,我们准备将 API 指令发送至 openFDA 数据服务器。首先调入 requests 包,之后通过 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 中的内容,但此时屏幕列示的 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 med
> ical care. While we make every effort to ensure that data is accurate, you sh
> ould assume all results are unvalidated. We may limit or otherwise restrict y
> our access to the API in line with our Terms of Service.'
'terms''https://
> open.fda.gov/terms/'
'license''https://open.fda.gov/license/''last_updat
> ed'
'2020-10-24'}, 'results': [{'time''20180101''count'1}, {'time''2
> 0180102'
'count'16}, {'time''20180103''count'20}, {'time''20180104
> '
'count'25}, {'time''20180105''count'24}]}
>>> end
--------------------------------------------------

为了提高数据的可读性,我们可以加载 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 medic
> al care. While we make every effort to ensure that data is accurate, you shou
> ld assume all results are unvalidated. We may limit or otherwise restrict you
> r access to the API in line with our Terms of Service."
,
        "last_updated""2020-10-24",
        "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
--------------------------------------------------

5. 将 JSON 数据转化为 Stata 数据集

我们可以使用 requests.get() 来提取 "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 中的数据仍然是以键值对存在,我们需要把它进一步转化为 dataframe 形式的。因此,我们需要调入 pandas 模块,然后利用 read_json() 来读取 fdadata 中的数据并存为 fda_df

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
. 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()fda_df 保存为「fentanyl.dta」,选项 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

列示「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 日 (见最下面的代码块),并绘制下图:

python:
# Import packages
import requests
import json
import pandas as pd

# Construct the URL for the API call
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

# Submit the API data request
data = requests.get(URL).json()

# Extract the 'results' part of the JSON data
fdadata = data.get('results', [])

# Convert the JSON data to a pandas data frame
fda_df  = pd.read_json(json.dumps(fdadata))

# Use pandas to write the data frame to a Stata 16 dataset
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)

6. 结语

至此,我们已成功地将 API 指令发送给了「openFDA」,得到了 JSON 数据,并且将其转化为了 Stata 数据集格式。

类似的方法,我们也可以在「巨潮资讯」网站,根据链接 http://www.cninfo.com.cn/new/data/szse_stock.json 获取股票信息。

7. 相关推文

Note:产生如下推文列表的命令为:
lianxh Stata Python +
安装最新版 lianxh 命令:
ssc install lianxh, replace

  • 专题:Stata入门
    • 使用 Jupyter Notebook 配置 Stata\Python\Julia\R
  • 专题:Stata程序
    • Stata程序:是否有类似-Python-中的-zip()-函数
  • 专题:文本分析-爬虫
    • VaR 风险价值: Stata 及 Python 实现
    • 支持向量机:Stata 和 Python 实现
  • 专题:Python-R-Matlab
    • Stata交互:Python-与-Stata-对比
    • Python+Stata:批量制作个性化结业证书
  • 专题:其它
    • ES 期望损失: Stata 及 Python 实现

🍓 课程推荐:公开课:Stata+R 软件基础
嘉宾:候丹丹
扫码进群 获取资料及听课链接!

尊敬的老师 / 亲爱的同学们:

连享会致力于不断优化和丰富课程内容,以确保每位学员都能获得最有价值的学习体验。为了更精准地满足您的学习需求,我们诚挚地邀请您参与到我们的课程规划中来。 请您在下面的问卷中,分享您 感兴趣的学习主题或您希望深入了解的知识领域 。您的每一条建议都是我们宝贵的资源,将直接影响到我们课程的改进和创新。 我们期待您的反馈,因为您的参与和支持是我们不断前进的动力。感谢您抽出宝贵时间,与我们共同塑造更加精彩的学习旅程!https://www.wjx.cn/vm/YgPfdsJ.aspx# 再次感谢大家宝贵的意见!

New! Stata 搜索神器:lianxh 和 songbl  GIF 动图介绍
搜: 推文、数据分享、期刊论文、重现代码 ……
👉 安装:
  . ssc install lianxh
  . ssc install songbl
👉  使用:
  . lianxh DID 倍分法
  . songbl all

🍏 关于我们

  • 连享会 ( www.lianxh.cn,推文列表) 由中山大学连玉君老师团队创办,定期分享实证分析经验。
  • 直通车: 👉【百度一下: 连享会】即可直达连享会主页。亦可进一步添加 「知乎」,「b 站」,「面板数据」,「公开课」 等关键词细化搜索。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/176687
 
190 次点击