作者选择了 自由和开源基金作为 写给捐款计划的一部分接受捐款。
介绍
类似于 Excel 表格或 SQL表,一个 pandas
DataFrame是一个两维数据结构,数据以行和列呈现。
使用 Python,您可以将 CSV、Excel 或 API 终端中的数据转换成一个pandas
数据框架,然后在获得的数据框架上工作。
有些 API 端点确实存在于字典的阅读友好的格式中,其中密钥代表列名和值代表属于这些列的元素。
在本教程中,您将从未分类的端点获取数据,并以适当的格式呈现给‘panda’ DataFrame。 首先,您将从一些常规 API 格式中提取数据,以便为将分类的 API 数据转换为 DataFrame 提供一些背景。
前提条件
要遵循本教程,您将需要:
对于 Ubuntu 和其他 Linux 发行版,请遵循我们关于 How To Install Python 3 and Set Up a Programming Environment的教程的步骤 1 和 2。对于 macOS,请遵循我们关于 How To Install Python 3 and Set Up a Local Programming Environment on macOS的教程步骤 1-5。对于其他操作系统,请检查 Jupyter Notebook Experience 安装和在您的机器上运行的官方文档。对于运行 Ubuntu/Debian 的远程服务器,请遵循 How to Install, Run, and Connect to Jupyter Notebook on a Remote Server的教程。对于其他操作系统,请检查 [Jupytery 安装的官方文档
步骤 1 – 准备您的Jupyter笔记本环境
对于本教程,您将使用 Jupyter 笔记本与数据一起工作,Jupyter 笔记本对于迭代编码是有用的,因为它允许您写一个小片段的代码,运行它,并返回结果。
要在您的 Jupyter 笔记本中遵循本教程,您需要打开一个新的笔记本并安装所需的依赖,您将在此步骤中完成。
在前提条件下,您在您的服务器上设置了一个Jupyter笔记本环境. 一旦您登录到您的服务器,启用虚拟环境:
1[environment local]
2source ~/environments/my_env/bin/activate
然后运行Jupyter笔记本应用程序来启动应用程序:
1[environment local]
2jupyter notebook
<$>[注] 注: 如果您正在远程服务器上遵循教程,您可以在本地机器的浏览器中使用端口转发访问您的Jupyter笔记本。
打开新终端并输入以下命令:
1[environment local]
2ssh -L 8888:localhost:8888 your_non_root_user@your_server_ip
当您连接到服务器时,请导航到输出提供的链接,以访问您的Jupyter笔记本。
在运行并连接到它后,您将访问基于浏览器的用户界面。从 New下载菜单中,选择 **Python3(ipykernel)**选项,这将打开一个新的卡片,带有未标题的Python笔记本。给您的文件一个名字;在本教程中,该文件被命名为 convert_data.ipynb
。
然后,在浏览器的Jupyter笔记本的第一个单元格中,使用pip
来安装必要的依赖:
1[label convert_data.ipynb]
2pip install pandas
3pip install requests
DataFrame 数据结构只能通过 pandas
模块访问,而 requests
模块可以帮助您访问 URL。
将命令添加到您的 Jupyter 笔记本后,请按 ** Run** 执行它们。
Jupyter 笔记本将提供一个运行输出,表示依赖性正在下载. 此输出下方将提供一个新的输入单元格,这就是您将运行下一行代码的地方。
接下来,通过运行以下命令导入您刚刚安装的模块:
1[label convert_data.ipynb]
2import pandas as pd
3import requests
「pd」将作为您调用「pandas」模块的捷径,您可以通过只写「pd」来调用「pandas」模块。
在此步骤中,您已经准备了您的 Jupyter 笔记本环境,接下来,您将执行一些基本的转换来从字典创建 DataFrames。
步骤 2 — 将排序的 API 数据转换为pandas
数据框架
在从未分类的 API 端点获取数据之前,您首先将从不同格式的字典和在 URL 上组织的 API 数据创建 DataFrames。
在许多 API 终端中,密钥通常代表列名,这些密钥的值代表属于各个列的元素,但是,有些 API 终端并不以这种格式呈现,这意味着您需要一种方法来提取列名及其相应的数据,以创建一个可读的字典,从中可以创建一个panda
数据框。
在此步骤中,您将使用一些常见的方法从不同格式的字典创建数据框。
方法 1 – 从字典列表创建数据框架
在此方法中,列表中的每个字典代表了最终数据框架中的数据行. 数据框架结构将包含代表列名称的密钥,其中包含属于列元素的值。
对于此方法,您将创建一个数据框,其中包含列年龄
,ID
和名称
,以及三个个人的信息。
在新单元格中,运行以下代码来格式化分配给变量 dict1
的字典列表(请自由用自己的名称替换):
1[label convert_data.ipynb]
2dict1=[{"Age":41,"ID":1234,"Name":"Bella"},{"Age":24,"ID":5678,"Name":"Mark"},{"Age":26,"ID":2341,"Name":"John"}]
3
4data=pd.DataFrame(dict1)
5
6data.head()
您将字典列表分配给dict1
变量. 列表中的每个字典代表了结果数据框的单行。 键年龄
、ID
和名称
代表了列名称。 每个键分配的值代表了该行列的值。 然后您将这个字典传递到pandas
模块中,以创建数据框。
以下数据框将打印:
1[secondary_label Output]
2Age ID Name
30 41 1234 Bella
41 24 5678 Mark
52 26 2341 John
您在dict1
列表中的每个字典中定义的密钥是获得的DataFrame中的列名,而这些字典中的值代表了行式数据。
方法 2 — 从单个字典创建数据框架
在前一种方法中,您根据行定义了数据,从而在列表中输入了多个字典,每个字典代表了行式的数据,其中密钥是列名称,值是属于列的元素。
此时,您将使用一个字典,其密钥代表列名,但其值是代表该列垂直数据的列表。
若要使用此方法,您可以使用在上一节中使用的相同数据,在新单元格中运行以下行:
1[label convert_data.ipynb]
2dict2={"Age":[41,24,26],"ID":[1234,5678,2341],"Name":["Bella","Mark","John"]}
3
4data=pd.DataFrame(dict2)
5
6data.head()
在这里,您可以使用字典定义列式的数据。dict2
字典中的密钥是列名称:年龄
,ID
和名称
。
以下数据框将打印到屏幕上:
1[secondary_label Output]
2Age ID Name
30 41 1234 Bella
41 24 5678 Mark
52 26 2341 John
字典dict2
中的密钥代表了列名(年龄
、ID
和名称
),每个列都包含您定义为每个密钥的值的列表,例如年龄
列有值41
,24
和26
。
虽然前两种方法的输出相同,但您可以使用行式和列式方法创建数据框。
方法 3 — 在 URL 上使用 API 数据创建数据框架
在 API 相关的 URL 中,数据通常呈现为类似于方法 1 中使用的数据的字典列表,但而不是硬编码数据,您将使用 requests
模块访问 URL 上的 API 数据,这有助于您访问 URL。
对于此方法,您将使用 JSON API 的 URL: Capital Countries,该 URL 以 API 格式列出各国及其首都的列表。
1[environment second]
2https://raw.githubusercontent.com/dariusk/corpora/master/data/geography/countries_with_capitals.json
以下是由 URL 提供的 API 数据的开始部分:
1[label List of Countries with Capitals (API Data from the Countries with Capitals URL)]
2[environment second]
3{
4 "description": "A list of countries and its respective capitals.",
5 "countries": [
6 {"name":"Afghanistan", "capital":"Kabul"},
7 {"name":"Albania", "capital":"Tirana"},
8 {"name":"Algeria", "capital":"Algiers"},
9 {"name":"Andorra", "capital":"Andorra la Vella"},
10 {"name":"Angola", "capital":"Luanda"},
11 {"name":"Antigua & Barbuda", "capital":"St. John's"},
12 {"name":"Argentina", "capital":"Buenos Aires"},
13 {"name":"Armenia", "capital":"Yerevan"},
14 {"name":"Australia", "capital":"Canberra"},
15 {"name":"Austria", "capital":"Vienna"},
16...
API以可识别的格式呈现:外部字典中的国家
键包含一份字典列表,其中名称
和资本
是列名,其相应值是行式数据。
若要从此 URL 创建一个pandas
数据框,请在新单元格中运行以下代码:
1[label convert_data.ipynb]
2response=requests.get('https://raw.githubusercontent.com/dariusk/corpora/master/data/geography/countries_with_capitals.json').json()
3
4df1=pd.DataFrame(response['countries'])
5
6df1.head()
请求
模块允许您获取访问 URL. 在这种情况下,您将 URL 读取为json
文件,并将读取数据分配给变量响应
。接下来,您将这个词典列表(作为国家
键的值提供)呈现给panda
,这反过来会提供一个DataFrame。
运行上述代码后,您将收到以下数据框:
1[secondary_label Output]
2 name capital
30 Afghanistan Kabul
41 Albania Tirana
52 Algeria Algiers
63 Andorra Andorra la Vella
74 Angola Luanda
这是你在将国家和首都列表转移到pandas
数据框架后获得的数据框架。当你运行此代码时,你将词典列表(作为国家
键的值)转移到pandas
数据框架模块中。列名为名称
和首都
,因为它们在该列表中的每个词典中都存在作为密钥,它们的值代表了行式数据(因为每个词典代表一个行)。
到目前为止,您已经从基本字典和结构化 API 终端点创建了 DataFrames。处理包含结构化 API 的 URL 时,数据通常以方法 1 中使用的格式呈现,作为一个字典列表,每个字典代表了行式数据。在API 数据非结构化的情况下,您可以使用方法 1 或 2 中的格式提取列名及其数据,以行式或列式的方式。
步骤 3 — 将无序的 API 数据转换为pandas
数据框架
到目前为止,您已经使用多种方法将排序数据转换为pandas
数据框,现在您将以不同的格式处理数据,此新 URL 中的 API 数据不是传统格式,因此很难识别列名及其数据。
首先,您将提取列名和所有列的值,然后将列名定义为密钥,列元素(在列表中)作为字典中的值。
此步骤使用来自纽约学校人口统计和问责 snapshot(https://data.cityofnewyork.us/api/views/ihfw-zy9j/rows.json)的数据。
在 API 终端中跟踪列名
在本节中,您将跟踪与 API 终端中包含的数据列相关的信息。
要访问样本数据,请通过您选择的 Web 浏览器打开此 URL:
1[environment second]
2https://data.cityofnewyork.us/api/views/ihfw-zy9j/rows.json
该 URL 中的数据比您在 步骤 2中使用的数据更容易呈现)。 NY Snapshot 数据呈现了一种或另一种形式的字典,但它们不是字典,其中密钥代表列名称,值代表列的元素。
您将首先找到与数据框架列相关的信息,在访问浏览器中的API URL时,请键入CTRL+F
并搜索列
:
1[environment second]
2[label The Columns Section (API data from the NY School Snapshot URL)]
3...
4"columns" : [ {
5 "id" : -1,
6 "name" : "sid",
7 "dataTypeName" : "meta_data",
8 "fieldName" : ":sid",
9 "position" : 0,
10 "renderTypeName" : "meta_data",
11 "format" : { },
12 "flags" : [ "hidden" ]
13 }, {
14 "id" : -1,
15 "name" : "id",
16 "dataTypeName" : "meta_data",
17 "fieldName" : ":id",
18 "position" : 0,
19 "renderTypeName" : "meta_data",
20 "format" : { },
21 "flags" : [ "hidden" ]
22 }, {
23 "id" : -1,
24 "name" : "position",
25 "dataTypeName" : "meta_data",
26 "fieldName" : ":position",
27 "position" : 0,
28 "renderTypeName" : "meta_data",
29 "format" : { },
30 "flags" : [ "hidden" ]
31...
在每个字典中,注意dataTypeName
键的值。对于前八个字典,dataTypeName
键的值是meta_data
。Metadata
是描述数据的数据。在这种情况下,元数据不是表中包含的数据,而是描述整个表的数据。因此,这八个字典(包含meta_data
作为其dataTypeName
键的值)并不代表表中的列信息。
但是,当您继续在这个列表中时,请注意没有meta_data
作为值的dataTypeName
键的第一个外观:
1[environment second]
2[label The Columns Section (API data from the NY School Snapshot URL)]
3...
4}, {
5 "id" : -1,
6 "name" : "meta",
7 "dataTypeName" : "meta_data",
8 "fieldName" : ":meta",
9 "position" : 0,
10 "renderTypeName" : "meta_data",
11 "format" : { },
12 "flags" : [ "hidden" ]
13 }, {
14 "id" : 45985351,
15 "name" : "DBN",
16 "dataTypeName" : "text",
17 "fieldName" : "dbn",
18 "position" : 1,
19 "renderTypeName" : "text",
20 "tableColumnId" : 8032537,
21 "cachedContents" : {
22 "non_null" : "10075",
23...
具有 45985351
值的词典是第一个没有 meta_data' 作为
dataTypeName' 密钥的值的词典。相反,这个值是 text' 这个词典描述了有关您可能数据集的第一个列的信息。这个词典的元素是
text' 格式(换句话说,字符串)。 这个第一个词典有 DBN' 值为
name' 密钥,表示 DBN' 是您的第一个列的名称。 所有词典(在
columns' 密钥中)跟随这个词典没有 meta_data' 作为数据
TypeName' 密钥的值,表明所有这些词典都代表了您的 DataFrame 下一个列的信息。
现在,您已经了解了如何找到有关表列的信息的基本知识,您将在下一步获取这些列的名称。
查找列名
在本节中,您将从 API 端点添加所有列的名称到名为列
的列表中,然后将以下行添加到 Jupyter 笔记本中的新单元格中,然后运行该单元格:
1[label convert_data.ipynb]
2response=requests.get('https://data.cityofnewyork.us/api/views/ihfw-zy9j/rows.json').json()
3
4columns=[]
5
6for i in response['meta']['view']['columns']:
7
8 if(i['dataTypeName']=='meta_data'):
9
10 continue
11 else:
12
13 columns.append(i['name'])
类似于您在 步骤 2中的方法 3 中所做的,您将通过请求
模块阅读此URL中的数据,并将其分配到名为响应
的变量中。
在行3中,您定义了列
列表,而在行5中,您定义了列
键在视图
键的值中,该值反过来又定义在元
键的值中。
for
循环通过附加到列
键的列表中的每个字典进行迭代,并检查这些字典的dataTypeName
键的值。如果当前字典的dataTypeName
键的值等于meta_data
,则跳过到下一个字典。
接下来,检查列表
中的内容,在新单元格中运行下列行:
1[label convert_data.ipynb]
2columns
列名将打印到屏幕上:
1[secondary_label Output]
2['DBN',
3'Name',
4'schoolyear',
5'fl_percent',
6'frl_percent',
7'total_enrollment',
8'prek',
9'k',
10'grade1',
11'grade2',
12'grade3',
13'grade4',
14'grade5',
15'grade6',
16'grade7',
17'grade8',
18'grade9',
19'grade10',
20'grade11',
21'grade12',
22'ell_num',
23'ell_percent',
24'sped_num',
25'sped_percent',
26'ctt_num',
27'selfcontained_num',
28'asian_num',
29'asian_per',
30'black_num',
31'black_per',
32'hispanic_num',
33'hispanic_per',
34'white_num',
35'white_per',
36'male_num',
37'male_per',
38'female_num',
39'female_per']
输出确认任何列的dataTypeName
不是meta_data
已被添加到列
列表中。
在本节中,您在未分类的API端点中获得了列表列表,您将需要创建最终的DataFrame。接下来,您将提取属于列
列表中定义的列表中的数据。
定义一个n
次数列表
在本节中,您将确定API中的列数,并定义与此数字相符的子列表列表。
最后,您正在使用 [步骤 2] 的方法 2(https://andsky.com/tech/tutorials/how-to-obtain-a-pandas-dataframe-from-an-unordered-api-endpoint#step-2-converting-ordered-api-data-into-pandas-dataframe)从一个字典中获取一个pandas
数据框,其密钥代表列名,而这些密钥的值是代表各列元素的列表。
一旦您使用此操作定义了字典,您将能够通过列
列表和子列表
列表循环动态地对字典进行添加,例如,指数0
下的子列表将作为列
列表中的0
列表中的列表名称的元素列表,同样,指数1
下的子列表也将作为列
列表中的1
列表名称的元素列表。
在之前的步骤中,您获得了列表列表名称. 现在,您将通过在新单元格中运行此行来检查该列表的长度:
1[label convert_data.ipynb]
2len(columns)
len(列)
返回列表中的项目数。
API 中存在的列数将打印到屏幕上:
1[secondary_label Output]
238
由于您有38
列,您将定义一个38
子列表列表,每个子列表将包含每个列的数据。
在新单元格中运行以下代码,创建38
子列表的列表(命名为d
):
1[label convert_data.ipynb]
2d = [[] for x in range(len(columns))]
3
4d
要创建列表,请先命名列表(在这种情况下,d)。数据集中的每个数组([])将创建一个新的子列表,其中包含您刚刚找到的
38 列范围中的数据。
下面的输出显示了38
子列表的列表:
1[secondary_label Output]
2[[],
3[],
4[],
5[],
6[],
7[],
8[],
9[],
10[],
11[],
12[],
13[],
14[],
15[],
16[],
17[],
18[],
19[],
20[],
21[],
22[],
23[],
24[],
25[],
26[],
27[],
28[],
29[],
30[],
31[],
32[],
33[],
34[],
35[],
36[],
37[],
38[],
39[]]
这些子列表最初是空的,因为您尚未添加任何元素。
您现在在d
列表中创建了38
子列表,这些38
子列表的内容将代表38
列的列式数据。
获取列的值
在本节中,您将从 API 终端中提取列式数据,并将该数据附加到您在最后一步创建的38
子列表中。
在浏览器中访问 API URL 时,请键入CTRL+F
并搜索数据
。 将有大约73
的发生。
1[environment second]
2[label The Data Portion Showing Sublists (API Data from the NY School Snapshot URL)]
3...
4"data" : [ [ "row-h6zp~rx75.iwiv", "00000000-0000-0000-C205-81EF0C7F0969", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE", "20052006", "89.4", null, "281", "15", "36", "40", "33", "38", "52", "29", "38", null, null, null, null, null, null, "36", "12.8", "57", "20.3", "25", "9", "10", "3.6", "74", "26.3", "189", "67.3", "5", "1.8", "158", "56.2", "123", "43.8" ]
5, [ "row-bgbf_ntuw.ckdq", "00000000-0000-0000-9AF5-4D58BAF51C20", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE", "20062007", "89.4", null, "243", "15", "29", "39", "38", "34", "42", "46", null, null, null, null, null, null, null, "38", "15.6", "55", "22.6", "19", "15", "18", "7.4", "68", "28", "153", "63", "4", "1.6", "140", "57.6", "103", "42.4" ]
6, [ "row-mspc-8wz5_uxb8", "00000000-0000-0000-9E11-73B99A1B02D9", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE", "20072008", "89.4", null, "261", "18", "43", "39", "36", "38", "47", "40", null, null, null, null, null, null, null, "52", "19.9", "60", "23", "20", "14", "16", "6.1", "77", "29.5", "157", "60.2", "7", "2.7", "143", "54.8", "118", "45.2" ]
7, [ "row-p6za~9ikt~ums7", "00000000-0000-0000-D2CD-5904BA5DC16E", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE", "20082009", "89.4", null, "252", "17", "37", "44", "32", "34", "39", "49", null, null, null, null, null, null, null, "48", "19", "62", "24.6", "21", "17", "16", "6.3", "75", "29.8", "149", "59.1", "7", "2.8", "149", "59.1", "103", "40.9" ]
8, [ "row-55ss_ktcg~w7ru", "00000000-0000-0000-9425-35118FA9200F", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE", "20092010", " ", "96.5", "208", "16", "40", "28", "32", "30", "24", "38", null, null, null, null, null, null, null, "40", "19.2", "46", "22.1", "14", "14", "16", "7.7", "67", "32.2", "118", "56.7", "6", "2.9", "124", "59.6", "84", "40.4" ]
9, [ "row-ugmn-sxmy_fyiu", "00000000-0000-0000-2070-ABC0343F1148", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE", "20102011", " ", "96.5", "203", "13", "37", "35", "33", "30", "30", "25", null, null, null, null, null, null, null, "30", "14.8", "46", "22.7", "21", "9", "13", "6.4", "75", "36.9", "110", "54.2", "4", "2", "113", "55.7", "90", "44.3" ]
10, [ "row-a4rf-xqy7~fvkh", "00000000-0000-0000-AF7F-41FA5EB8E91E", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE ", "20112012", null, "89.4", "189", "13", "31", "35", "28", "25", "28", "29", " ", " ", " ", " ", " ", " ", " ", "20", "10.6", "40", "21.2", "23", "7", "12", "6.3", "63", "33.3", "109", "57.7", "4", "2.1", "97", "51.3", "92", "48.7" ]
11...
在分配给数据
密钥的列表中,每个子列表都显示了您的潜在数据框的单行值. 要确定实际的行式数据开始的地方,您需要将列数与数据
部分的单一子列表中的元素数量进行比较。
通过在新单元格中运行下列行来确认列的数量:
1[label convert_data.ipynb]
2len(columns)
以下输出将打印列的数量:
1[secondary_label Output]
238
接下来,检查数据
中的第一个子列表的长度,这是第一个行中的值数:
1[label convert_data.ipynb]
2
3len(response['data'][0])
您在数据
中指定第一个子列表,其ID号为0
。
以下输出将打印数据
中的第一个子列表中的元素数目:
1[secondary_label Output]
246
您可能认为,由于数据是行式的,所以第一个子列表(46
)中的元素数量将等于列数(38
)。然而,每个子列表的长度为 46
,这意味着 8
比 38
多。请记住,您在列
键中发现了8
字典,其中meta_data
作为dataTypeName
键的值。
由于列表中的索引从0
开始,您现在知道这些子列表的值在0
到7
范围内(包括)并不代表DataFrame内容,而是代表元数据值。
您将从数据
子列表中添加元素,使用循环从索引46-38
(8
)到索引46
。 要测试这一点,您将从第一行中提取数据(而不是从所有子列表中提取所有数据)。
1[label convert_data.ipynb]
2count=0
3
4for i in response['data'][0][len(response['data'][0])-len(columns):len(response['data'][0])]: #from index 8 to 45
5
6 d[count].append(i)
7
8 count=count+1
9
10d
在这种情况下,变量数
有助于将第一行的列数据附加到d
的nth子列表中。
然后,代码通过数据
中的第一个子列表进行迭代,以获得从索引8
开始的元素,并在索引45
结束的元素(结果是38
元素)。
「答案(答案)」表示数据
键中的第一个子列表的长度,而「len(列)」表示列
列表的长度,表示最终数据框的列表数量。
以下是发生在前几次迭代中的概述。计数最初为0
。当您输入for
循环时,i
是response[
data][0][8]
,这是第一个子列表中的第一个非元数据值。
当 i 是 响应[数据] [0][9] (第一个子列表中的第二个非元数据值) 时,你会将 i 值添加到 d[1] (现在的 0 是 1,因为在上一次迭代中, count 被增加到 1 ) 因此,这个值会被添加到列表中的第二个子列表d。
输出显示了第一行数据:
1[secondary_label Output]
2[['01M015'], ['P.S. 015 ROBERTO CLEMENTE'], ['20052006'], ['89.4'], [None], ['281'], ['15'], ['36'], ['40'], ['33'], ['38'], ['52'], ['29'], ['38'], [None], [None], [None], [None], [None], [None], ['36'], ['12.8'], ['57'], ['20.3'], ['25'], ['9'], ['10'], ['3.6'], ['74'], ['26.3'], ['189'], ['67.3'], ['5'], ['1.8'], ['158'], ['56.2'], ['123'], ['43.8']]
要检查第一个行是否包含正确的数据,请将其与 API URL 中的数据
键作为值的列表中的第一个子列表进行比较:
1[environment second]
2[label Elements of the First Sublist (API Data from the NY School Snapshot URL)]
3...
4"data" : [ [ "row-h6zp~rx75.iwiv", "00000000-0000-0000-C205-81EF0C7F0969", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE", "20052006", "89.4", null, "281", "15", "36", "40", "33", "38", "52", "29", "38", null, null, null, null, null, null, "36", "12.8", "57", "20.3", "25", "9", "10", "3.6", "74", "26.3", "189", "67.3", "5", "1.8", "158", "56.2", "123", "43.8" ]
5...
您可能需要向上面的框的右边滚动以查看完整的数据片段。
最初的几个值(从索引 0
到 7
)代表与元数据列相关的信息. 第一子列表中的突出值(从索引 8
到 45
)是第一行的值,您已成功提取。
要在所有行中执行相同的任务,您需要更新以前的代码。 首先,在新单元格中运行下列行来重新定义d
列表的38
子列表:
1[label convert_data.ipynb]
2d = [[] for x in range(len(columns))]
您正在重新定义d
列表,因为d
子列表列表目前包含第一行中的所有元素,现在您的目标是执行相同的操作,但包括第一行在内的所有剩余行。
现在您已创建一个新的38
子列表列表,在新的单元格中运行以下行,该单元格对未来数据框的所有行进行数据提取:
1[label convert_data.ipynb]
2for i in response['data']:
3 count=0
4 for j in range(len(response['data'][0])-len(columns),len(response['data'][0])):
5 d[count].append(i[j])
6 count+=1
在第 1 行中,for i in response[‘data’]
意味着i
被分配给每个子列表一个接一个。
这里有几个迭代的概述. 您从i
开始,列表中的第一个子列表分配给了data
键。
在Python中,for
循环的上限是专属的,所以你会从索引8
到45
的元素。
d[count].append(i[j])
的意思是d[0].append(i[8])
,意思是你正在将第一个子列表的索引8
中的元素附加到列表d
的第一个子列表中。
现在4行是d(附加)(i[9])
,这意味着第一个子列表的索引9
中的元素(仍然按外部循环分配给i
)被附加到列表d
的第二个子列表中。
在内部循环的末尾,附加第一个行最后一个值的操作将是这样的: d[37].append(i[45])
. 在第一个迭代的末尾,列表 d
看起来与之前的输出相同(在所有子列表中的 d
只有一个元素)。
当您突破内部循环时,您将进入外部循环。 i
被分配给数据
键分配的列表中的下一个子列表(第二次子列表)。
当您在这个i
的第二次迭代中突破内部循环时,所有d
的子列表现在将有两个值,每个子列表的第二个值代表属于第二行的数据。
为了让您了解d
的子列表中所获得的数据的外观,您将获取d
的前三个子列表中的前五个元素,在结果的数据框中,这些值将是前三个列中的前五个元素。
首先,通过对d
的0
索引下次列表的前五个元素进行审查:
1[label convert_data.ipynb]
2d[0][0:5]
输出将显示如下:
1[secondary_label Output]
2['01M015', '01M015', '01M015', '01M015', '01M015']
您可以通过将其与 API 的数据
部分进行比较来验证输出,当您在浏览器中查看时:
1[environment second]
2[label Elements of the First Sublist (API Data from the NY School Snapshot URL)]
3...
4"data" : [ [ "row-h6zp~rx75.iwiv", "00000000-0000-0000-C205-81EF0C7F0969", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE", "20052006", "89.4", null, "281", "15", "36", "40", "33", "38", "52", "29", "38", null, null, null, null, null, null, "36", "12.8", "57", "20.3", "25", "9", "10", "3.6", "74", "26.3", "189", "67.3", "5", "1.8", "158", "56.2", "123", "43.8" ]
5, [ "row-bgbf_ntuw.ckdq", "00000000-0000-0000-9AF5-4D58BAF51C20", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE", "20062007", "89.4", null, "243", "15", "29", "39", "38", "34", "42", "46", null, null, null, null, null, null, null, "38", "15.6", "55", "22.6", "19", "15", "18", "7.4", "68", "28", "153", "63", "4", "1.6", "140", "57.6", "103", "42.4" ]
6, [ "row-mspc-8wz5_uxb8", "00000000-0000-0000-9E11-73B99A1B02D9", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE", "20072008", "89.4", null, "261", "18", "43", "39", "36", "38", "47", "40", null, null, null, null, null, null, null, "52", "19.9", "60", "23", "20", "14", "16", "6.1", "77", "29.5", "157", "60.2", "7", "2.7", "143", "54.8", "118", "45.2" ]
7, [ "row-p6za~9ikt~ums7", "00000000-0000-0000-D2CD-5904BA5DC16E", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE", "20082009", "89.4", null, "252", "17", "37", "44", "32", "34", "39", "49", null, null, null, null, null, null, null, "48", "19", "62", "24.6", "21", "17", "16", "6.3", "75", "29.8", "149", "59.1", "7", "2.8", "149", "59.1", "103", "40.9" ]
8, [ "row-55ss_ktcg~w7ru", "00000000-0000-0000-9425-35118FA9200F", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE", "20092010", " ", "96.5", "208", "16", "40", "28", "32", "30", "24", "38", null, null, null, null, null, null, null, "40", "19.2", "46", "22.1", "14", "14", "16", "7.7", "67", "32.2", "118", "56.7", "6", "2.9", "124", "59.6", "84", "40.4" ]
9,
10...
您可能需要向上面的框的右边滚动以查看完整的数据片段。
您获取的值与所突出的值相匹配,这些值在每个子列表的索引8
。指数范围中的这些子列表的元素0-7
(包括)代表了元数据值,而不是前瞻性数据框的值。
接下来,您可以在d
的1
索引下查看子列表的前五个元素:
1[label convert_data.ipynb]
2d[1][0:5]
第二次子列表的前五个元素将打印到屏幕上:
1[secondary_label Output]
2['P.S. 015 ROBERTO CLEMENTE',
3'P.S. 015 ROBERTO CLEMENTE',
4'P.S. 015 ROBERTO CLEMENTE',
5'P.S. 015 ROBERTO CLEMENTE',
6'P.S. 015 ROBERTO CLEMENTE']
这些值代表列
列表中的1
索引列表中的第五个列表元素:名称
。
1[environment second]
2[label Elements of the Second Sublist (API Data from the NY School Snapshot URL)]
3...
4"data" : [ [ "row-h6zp~rx75.iwiv", "00000000-0000-0000-C205-81EF0C7F0969", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE", "20052006", "89.4", null, "281", "15", "36", "40", "33", "38", "52", "29", "38", null, null, null, null, null, null, "36", "12.8", "57", "20.3", "25", "9", "10", "3.6", "74", "26.3", "189", "67.3", "5", "1.8", "158", "56.2", "123", "43.8" ]
5, [ "row-bgbf_ntuw.ckdq", "00000000-0000-0000-9AF5-4D58BAF51C20", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE", "20062007", "89.4", null, "243", "15", "29", "39", "38", "34", "42", "46", null, null, null, null, null, null, null, "38", "15.6", "55", "22.6", "19", "15", "18", "7.4", "68", "28", "153", "63", "4", "1.6", "140", "57.6", "103", "42.4" ]
6, [ "row-mspc-8wz5_uxb8", "00000000-0000-0000-9E11-73B99A1B02D9", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE", "20072008", "89.4", null, "261", "18", "43", "39", "36", "38", "47", "40", null, null, null, null, null, null, null, "52", "19.9", "60", "23", "20", "14", "16", "6.1", "77", "29.5", "157", "60.2", "7", "2.7", "143", "54.8", "118", "45.2" ]
7, [ "row-p6za~9ikt~ums7", "00000000-0000-0000-D2CD-5904BA5DC16E", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE", "20082009", "89.4", null, "252", "17", "37", "44", "32", "34", "39", "49", null, null, null, null, null, null, null, "48", "19", "62", "24.6", "21", "17", "16", "6.3", "75", "29.8", "149", "59.1", "7", "2.8", "149", "59.1", "103", "40.9" ]
8, [ "row-55ss_ktcg~w7ru", "00000000-0000-0000-9425-35118FA9200F", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE", "20092010", " ", "96.5", "208", "16", "40", "28", "32", "30", "24", "38", null, null, null, null, null, null, null, "40", "19.2", "46", "22.1", "14", "14", "16", "7.7", "67", "32.2", "118", "56.7", "6", "2.9", "124", "59.6", "84", "40.4" ]
9,
10...
您可能需要向上面的框右转,以查看完整的数据片段. 您获得的值匹配突出值。
最后,审查d
的索引2
下的子列表的前五个元素:
1[label convert_data.ipynb]
2d[2][0:5]
以下输出将打印到屏幕上:
1[secondary_label Output]
2['20052006', '20062007', '20072008', '20082009', '20092010']
通过 API URL 的数据
部分检查输出:
1[environment second]
2[label Elements of the Second Sublist (API data from the NY School Snapshot URL)]
3...
4"data" : [ [ "row-h6zp~rx75.iwiv", "00000000-0000-0000-C205-81EF0C7F0969", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE", "20052006", "89.4", null, "281", "15", "36", "40", "33", "38", "52", "29", "38", null, null, null, null, null, null, "36", "12.8", "57", "20.3", "25", "9", "10", "3.6", "74", "26.3", "189", "67.3", "5", "1.8", "158", "56.2", "123", "43.8" ]
5, [ "row-bgbf_ntuw.ckdq", "00000000-0000-0000-9AF5-4D58BAF51C20", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE", "20062007", "89.4", null, "243", "15", "29", "39", "38", "34", "42", "46", null, null, null, null, null, null, null, "38", "15.6", "55", "22.6", "19", "15", "18", "7.4", "68", "28", "153", "63", "4", "1.6", "140", "57.6", "103", "42.4" ]
6, [ "row-mspc-8wz5_uxb8", "00000000-0000-0000-9E11-73B99A1B02D9", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE", "20072008", "89.4", null, "261", "18", "43", "39", "36", "38", "47", "40", null, null, null, null, null, null, null, "52", "19.9", "60", "23", "20", "14", "16", "6.1", "77", "29.5", "157", "60.2", "7", "2.7", "143", "54.8", "118", "45.2" ]
7, [ "row-p6za~9ikt~ums7", "00000000-0000-0000-D2CD-5904BA5DC16E", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE", "20082009", "89.4", null, "252", "17", "37", "44", "32", "34", "39", "49", null, null, null, null, null, null, null, "48", "19", "62", "24.6", "21", "17", "16", "6.3", "75", "29.8", "149", "59.1", "7", "2.8", "149", "59.1", "103", "40.9" ]
8, [ "row-55ss_ktcg~w7ru", "00000000-0000-0000-9425-35118FA9200F", 0, 1425758466, null, 1425758466, null, "{ }", "01M015", "P.S. 015 ROBERTO CLEMENTE", "20092010", " ", "96.5", "208", "16", "40", "28", "32", "30", "24", "38", null, null, null, null, null, null, null, "40", "19.2", "46", "22.1", "14", "14", "16", "7.7", "67", "32.2", "118", "56.7", "6", "2.9", "124", "59.6", "84", "40.4" ]
9,
10...
您可能需要向上面的框右滚动,以查看完整的数据片段。 您获得的值与所突出的值相匹配. 最终,这些值代表了列
列表中的2
指数列的第五个元素:学年
。
随着此步骤的结束,您已成功提取所有38
列的所有行数据,并将其附加到d
列表的38
子列表中。
创建一个数据框架的字典
从这个步骤开始,您已经提取了每个38
列的名称和值,现在您将将其转移到pandas
数据框中,以字典格式。
在新单元格中运行以下代码:
1[label convert_data.ipynb]
2json_dict={}
3
4for i in range(0,len(columns)):
5 json_dict.update({columns[i]:d[i]})
您将通过0
到(但不包括)38
的范围循环,并将关键值对添加到最终的字典json_dict
,您将转移到pandas
数据框进行转换,因此,例如,当i
为0
,您将指数0
中的d
子列表分配为代码DBN
,由列[0]
表示,并将其转移到剩余的索引。
要想了解字典中获得的密钥将如何看,请查看 `json_dict' 中存在的所有密钥:
1[label convert_data.ipynb]
2json_dict.keys()
最终字典的关键列表将打印到屏幕上:
1[secondary_label Output]
2dict_keys(['DBN', 'Name', 'schoolyear', 'fl_percent', 'frl_percent', 'total_enrollment', 'prek', 'k', 'grade1', 'grade2', 'grade3', 'grade4', 'grade5', 'grade6', 'grade7', 'grade8', 'grade9', 'grade10', 'grade11', 'grade12', 'ell_num', 'ell_percent', 'sped_num', 'sped_percent', 'ctt_num', 'selfcontained_num', 'asian_num', 'asian_per', 'black_num', 'black_per', 'hispanic_num', 'hispanic_per', 'white_num', 'white_per', 'male_num', 'male_per', 'female_num', 'female_per'])
d
的38
子列表已被分配到json_dict
中的上述38
键中,因此,您获得了一个字典,其中关键是列名,值是包含每个列元素的列表。
现在将这个词典转移到pandas
来生成一个DataFrame. 这个DataFrame可以用你选择的变量名称命名(本教程使用data
):
1[label convert_data.ipynb]
2data=pd.DataFrame(json_dict)
接下来,审查结果数据框架的一部分:
1[label convert_data.ipynb]
2data.head()
DataFrame 的前五行将打印到屏幕上:
1[secondary_label Output]
2DBN Name schoolyear fl_percent frl_percent total_enrollment prek k grade1 grade2 ... black_num black_per hispanic_num hispanic_per white_num white_per male_num male_per female_num female_per
30 01M015 P.S. 015 ROBERTO CLEMENTE 20052006 89.4 None 281 15 36 40 33 ... 74 26.3 189 67.3 5 1.8 158 56.2 123 43.8
41 01M015 P.S. 015 ROBERTO CLEMENTE 20062007 89.4 None 243 15 29 39 38 ... 68 28 153 63 4 1.6 140 57.6 103 42.4
52 01M015 P.S. 015 ROBERTO CLEMENTE 20072008 89.4 None 261 18 43 39 36 ... 77 29.5 157 60.2 7 2.7 143 54.8 118 45.2
63 01M015 P.S. 015 ROBERTO CLEMENTE 20082009 89.4 None 252 17 37 44 32 ... 75 29.8 149 59.1 7 2.8 149 59.1 103 40.9
74 01M015 P.S. 015 ROBERTO CLEMENTE 20092010 96.5 208 16 40 28 32 ... 67 32.2 118 56.7 6 2.9 124 59.6 84 40.4
您可能需要向上面的框的右边滚动,以查看完整的DataFrame头部
。
结论
在本教程中,您使用了一些常见的方法来从各种格式的字典和 URL 创建一个pandas
数据框,您还创建了一个数据框从 API 终端,其中列和各自的值不会以简单的方式显示。
本教程应该帮助您了解如何使用独特的方法来创建DataFrames,使用从非传统API终端或字典中提取的数据。