無順序なAPIエンドポイントからpandasのデータフレームを取得する方法

著者は、書くことによる寄付プログラムの一環として、「フリー・オープンソース基金」に寄付することを選びました。

はじめに

ExcelスプレッドシートやSQLテーブルのように、pandasのDataFrameは行と列にデータが表示される二次元のデータ構造です。データフレームは、主に科学的な学習、データサイエンス、機械学習、データ分析など、データに重点を置いた分野で使用されています。

Pythonを使えば、CSV、Excel、またはAPIエンドポイントからデータをpandasのDataFrameに変換し、得られたDataFrameで作業することができます。ExcelやCSVファイルの変換は比較的簡単ですが、APIエンドポイントは異なることがあり、その情報からDataFrameを作成するのは難しい場合もあります。

一部のAPIエンドポイントは、読みやすい形式の辞書で提供されており、キーは列名を表し、値はその列に属する要素を表します。しかし、一部のAPIエンドポイントでは列名とその値が明確な文脈で表されておらず、順序のないAPIエンドポイントをDataFrameに変換することは困難です。

このチュートリアルでは、順不同のエンドポイントからデータを取得し、適切な形式でpandasのDataFrameに表示します。まず、順序付けられたAPIデータをDataFrameに変換するための文脈を提供するために、いくつかの従来のAPI形式からデータを抽出します。次に、順不同のAPIエンドポイントで作業します。列名とそれに対応する要素を抽出して辞書を作成します。最後に、この辞書をpandasのDataFrameに渡してデータ分析に使用できるようにします。

前提条件

このチュートリアルを進めるには、次のものが必要です。

  • Python 3, pip, and the Python venv module installed on your machine. For Ubuntu and other Linux distributions, follow Steps 1 and 2 of our tutorial on How To Install Python 3 and Set Up a Programming Environment. For macOS, follow Steps 1–5 of our tutorial on How To Install Python 3 and Set Up a Local Programming Environment on macOS.
  • Jupyter notebook installed and running on your machine. For remote servers running Ubuntu/Debian, follow How to Install, Run, and Connect to Jupyter Notebook on a Remote Server. For other operating systems, check the official documentation for installing Jupyter.
  • A modern web browser that you will use to access Jupyter Notebook.
  • Familiarity with the fundamentals of Python, such as for loops, functions, and data structures (in particular, lists and dictionaries).
  • Experience with the Python pandas module for data manipulation and analysis.

ステップ1 — Jupyter Notebookの環境準備

このチュートリアルでは、データを扱うためにJupyter Notebookを使用します。Jupyter Notebookは反復的なコーディングに役立ちます。小さなコードの断片を書き、実行し、結果を返すことができるからです。

このチュートリアルをJupyter Notebookでフォローするためには、新しいノートブックを開き、このステップで必要な依存関係をインストールする必要があります。

前提条件として、サーバー上にJupyter Notebookの環境を設定します。サーバーにログインしたら、仮想環境をアクティブにします。

  1. source ~/environments/my_env/bin/activate

 

その後、Jupyter Notebookアプリケーションを実行してアプリケーションを起動してください。

  1. jupyter notebook

 

Note

注意: リモートサーバーでチュートリアルを実行している場合、ポートフォワーディングを使用してローカルマシンのブラウザでJupyter Notebookにアクセスできます。
新しいターミナルを開き、次のコマンドを入力してください:
ssh -L 8888:localhost:8888 your_non_root_user@your_server_ip

サーバーに接続すると、出力で提供されるリンクに移動してJupyter Notebookにアクセスしてください。このターミナルはチュートリアルの終了まで開いたままにしておいてください。

実行して接続した後、ブラウザベースのユーザーインターフェースにアクセスします。新しいドロップダウンメニューから、Python3(ipykernel)オプションを選択してください。そうすると、無題のPythonノートブックが開かれた新しいタブが表示されます。ファイルに名前を付けてください。このチュートリアルでは、ファイルの名前はconvert_data.ipynbです。

その後、ブラウザのJupyter Notebookの最初のセルで、必要な依存関係をインストールするためにpipを使用してください。

「convert_data.ipynb」を日本語に翻訳してください。
pip install pandas
pip install requests

DataFrameデータ構造は、pandasモジュールを通じてのみアクセスできます。requestsモジュールは、URLへのアクセスを支援します。

Jupyter Notebookにコマンドを追加した後、実行するためにランボタンを押してください。

あなたのJupyter Notebookは、依存関係がダウンロードされていることを示す実行結果を提供します。この出力の下に新しい入力セルが利用可能になります。そこで次のコードを実行することができます。

次に、次のコマンドを実行して、インストールしたモジュールをインポートしてください。

データを変換する.ipynb
import pandas as pd
import requests

pdは、パンダモジュールを呼び出すためのショートカットとして機能します。pdと書くだけでパンダモジュールを呼び出すことができます。

このステップでは、Jupyter Notebookの環境を準備しました。次に、いくつかの基本的な変換を行って、辞書からデータフレームを作成します。

ステップ2 — 並べ替えられたAPIデータをpandas DataFrameに変換する

無順序のAPIエンドポイントからデータを取得する前に、まず異なる形式の辞書からデータフレームを作成し、URL上の整理されたAPIデータを用意します。

多くのAPIエンドポイントでは、通常、キーは列名を表し、それらのキーの値はそれぞれの列に属する要素を表します。しかし、一部のAPIエンドポイントはこの形式では提供されていません。つまり、列名とそれに対応するデータを抽出して、読みやすい辞書を作成し、その辞書からpandas DataFrameを作成するための方法が必要です。従来のAPIエンドポイントをpandas DataFrameに変換するための一般的な手法を確認することで、このタスクをサポートします。

このステップでは、異なる形式の辞書からデータフレームを作成するために、いくつかの一般的な方法を使用します。

方法1 — 辞書のリストからDataFrameを作成

この方法では、リスト内の各辞書が最終的なDataFrameの一行のデータを表します。DataFrameの構造は、列名を表すキーと、列に属する要素の値を特徴としています。

この方法では、3人の個人の情報を含む「年齢」、「ID」、および「名前」の列を持つデータフレームを作成します。

新しいセルで、変数dict1に割り当てられた辞書のリストをフォーマットするために、以下のコードを実行してください(お好みで名前を自分用に置き換えてください)。

データを変換するipynbファイルを変換します。
dict1=[{"Age":41,"ID":1234,"Name":"Bella"},{"Age":24,"ID":5678,"Name":"Mark"},{"Age":26,"ID":2341,"Name":"John"}]

data=pd.DataFrame(dict1)

data.head()

dict1変数に辞書のリストを割り当てます。リスト内の各辞書は、結果のDataFrameの1行を表します。Age、ID、およびNameというキーは列名を表します。各キーに割り当てられた値は、その行のその列の値を表します。それからこの辞書をpandasモジュールに渡してDataFrameを作成します。

以下のデータフレームが印刷されます。

Output

Age ID Name 0 41 1234 Bella 1 24 5678 Mark 2 26 2341 John

このDataFrameは辞書のリストから作成されました。dict1リスト内の各辞書で定義したキーは、取得したDataFrameの列名です。そして、これらの辞書内の値は、行方向のデータを表します。

方法2 – 単一の辞書からDataFrameを作成する

以前の方法では、行に基づいてデータを定義し、複数の辞書をリストに入力する必要がありました。各辞書は行方向のデータを表し、キーは列名、値は列に属する要素です。

今回は、データを列方向で定義します。辞書を使用し、キーは列名で、値はその列の縦のデータを表すリストです。

この方法を使うには、前のセクションで使用したデータと同じデータを使用することができます。次の行を新しいセルで実行してください。

データを変換するための「convert_data.ipynb」を作成してください。
dict2={"Age":[41,24,26],"ID":[1234,5678,2341],"Name":["Bella","Mark","John"]}

data=pd.DataFrame(dict2)

data.head()

ここでは、辞書を使って列ごとのデータを定義します。dict2のキーは列名であり、年齢、ID、名前です。各キーの値は、それぞれの列のデータを表すリストです。

以下のDataFrameは画面に表示されます:

Output

Age ID Name 0 41 1234 Bella 1 24 5678 Mark 2 26 2341 John

dict2のキーは(年齢、ID、名前)を表し、各列は、それぞれのキーの値として定義されたリストで埋められます。例えば、年齢列には、41、24、26の値が入ります。

やはり、両方の方法は同じ結果を生み出します。最初の2つの方法の出力は同じですが、行方向と列方向のアプローチの両方を使用してDataFrameを作成することができます。

方法3 — URLのAPIデータを使用してDataFrameを作成する

この方法では、URLから抽出したAPIデータを使用してDataFrameを作成します。API関連のURL内では、通常、Method 1で使用されるデータと同様の辞書のリスト形式でデータが提示されます。ただし、データをハードコーディングする代わりに、requestsモジュールを使用してURLからAPIデータにアクセスし、URLへのアクセスをサポートします。

この方法では、JSON APIのURLを使用します。このAPIは、「国と首都のリスト」をAPI形式で提供します。APIを表示するには、以下のURLをブラウザで開いてください。

  1. https://raw.githubusercontent.com/dariusk/corpora/master/data/geography/countries_with_capitals.json

 

URLで提供されるAPIデータの始めの部分を以下に示します。

「首都付き国の一覧(首都付き国のURLからのAPIデータ)」
{
  "description": "A list of countries and its respective capitals.",
  "countries": [
    {"name":"Afghanistan", "capital":"Kabul"},
    {"name":"Albania", "capital":"Tirana"},
    {"name":"Algeria", "capital":"Algiers"},
    {"name":"Andorra", "capital":"Andorra la Vella"},
    {"name":"Angola", "capital":"Luanda"},
    {"name":"Antigua & Barbuda", "capital":"St. John's"},
    {"name":"Argentina", "capital":"Buenos Aires"},
    {"name":"Armenia", "capital":"Yerevan"},
    {"name":"Australia", "capital":"Canberra"},
    {"name":"Austria", "capital":"Vienna"},
...

APIは認識可能な形式で提供されます。外部の辞書内のcountriesキーには、辞書のリストが含まれており、nameとcapitalが列名であり、それに対応する値が行ごとのデータとなっています。

このURLからpandasのDataFrameを作成するには、新しいセルで以下のコードを実行してください。

データの変換.ipynb
response=requests.get('https://raw.githubusercontent.com/dariusk/corpora/master/data/geography/countries_with_capitals.json').json()

df1=pd.DataFrame(response['countries'])

df1.head()

requestsモジュールを使用すると、URLにアクセスできます。この場合、URLをjsonファイルとして読み込み、読み込んだデータを変数responseに割り当てます。次に、この辞書のリスト(countriesキーの値として提供される)をpandasに提示し、pandasはDataFrameを提供します。df1は、与えられたAPIエンドポイントからデータを抽出して正常に取得したDataFrameです。

上記のコードを実行すると、次のようなDataFrameが表示されます。

Output

name capital 0 Afghanistan Kabul 1 Albania Tirana 2 Algeria Algiers 3 Andorra Andorra la Vella 4 Angola Luanda

リストの国と首都をpandas DataFrameに渡した後のDataFrameです。このコードを実行すると、辞書のリスト(国のキーとして値が表示される)をpandas DataFrameモジュールに渡しました。列の名前は、このリストのすべての辞書にキーとして存在するため、nameとcapitalです。また、値は行ごとのデータを表しています(各辞書が行を表しているため)。

これまでに、基本的な辞書や構造化された API エンドポイントから DataFrame を作成しました。構造化された API を含む URL を扱う場合、データは一般的に Method 1 で使用されているフォーマットとして提供されます。各辞書が行単位のデータを表す形式で、辞書のリストとして表現されます。API のデータが非構造化されている場合、Method 1 または Method 2 の形式を使用して、列名とそのデータを行単位または列単位で抽出することができます。次のステップでは、このステップで使用したいくつかの戦略を組み合わせて、非構造化の API エンドポイントからデータを取得します。

ステップ3 — 順不同のAPIデータをpandas DataFrameに変換する

これまでに、いくつかの方法を使用して注文されたデータをPandasのDataframeに変換してきました。しかし、今回は異なる形式のデータを扱うことになります。この新しいURLのAPIデータは通常の形式ではないため、列名とそのデータを識別することが難しいです。

この順不同のデータからDataFrameを作成するためには、追加の手順を踏む必要があります。まず、列名と列の値を抽出し、列名をキーとして列要素(リスト形式)を値とした辞書を定義します。最終的には、Method 2で使用される形式に似た見栄えの良い辞書を取得し、pandasに変換してDataFrameに表示します。

このステップでは、NY学校の人口統計と責任スナップショットのデータを使用します。

APIエンドポイント内のカラム名のトラッキング

このセクションでは、APIエンドポイント内に含まれるデータの列に関連する情報を追跡します。

サンプルデータにアクセスするために、お好きなウェブブラウザでこのURLを開いてください。

  1. https://data.cityofnewyork.us/api/views/ihfw-zy9j/rows.json

 

このURLのデータは、ステップ2で扱ったデータよりも見やすさに欠けます。NYスナップショットデータは、ある形式の辞書を提供しているが、キーが列名を表し、値が列の要素を表す辞書ではありません。行方向または列方向のデータを具体的に示す直接的な辞書は存在しないようです。

最初に、DataFrameに関連する情報を見つけることから始めます。ブラウザでAPIのURLにアクセスする際には、CTRL+Fを入力して”columns:”と検索します。

コラムセクション(NY校快見表URLからのAPIデータ)
...
"columns" : [ {
        "id" : -1,
        "name" : "sid",
        "dataTypeName" : "meta_data",
        "fieldName" : ":sid",
        "position" : 0,
        "renderTypeName" : "meta_data",
        "format" : { },
        "flags" : [ "hidden" ]
      }, {
        "id" : -1,
        "name" : "id",
        "dataTypeName" : "meta_data",
        "fieldName" : ":id",
        "position" : 0,
        "renderTypeName" : "meta_data",
        "format" : { },
        "flags" : [ "hidden" ]
      }, {
        "id" : -1,
        "name" : "position",
        "dataTypeName" : "meta_data",
        "fieldName" : ":position",
        "position" : 0,
        "renderTypeName" : "meta_data",
        "format" : { },
        "flags" : [ "hidden" ]
...

カラムキーの値リストには、複数の辞書があります。それぞれの辞書内には、dataTypeNamキーズの値に注目してください。最初の8つの辞書では、dataTypeNamキーの値がmeta_dataとなっています。メタデータは、データを説明するデータです。この場合、メタデータはテーブル内のデータではなく、テーブル全体を説明するデータです。したがって、dataTypeNamキーの値がmeta_dataとなっているこれらの8つの辞書は、テーブル内のカラムに関する情報を表していません。

しかし、このリストをさらに進めると、meta_dataを値として持たないdataTypeNameキーの最初の出現に注意してください。

コラムセクション(NY School SnapshotのAPIデータから取得)
...
}, {
       "id" : -1,
       "name" : "meta",
       "dataTypeName" : "meta_data",
       "fieldName" : ":meta",
       "position" : 0,
       "renderTypeName" : "meta_data",
       "format" : { },
       "flags" : [ "hidden" ]
     }, {
       "id" : 45985351,
       "name" : "DBN",
       "dataTypeName" : "text",
       "fieldName" : "dbn",
       "position" : 1,
       "renderTypeName" : "text",
       "tableColumnId" : 8032537,
       "cachedContents" : {
         "non_null" : "10075",
...

idが45985351の値を持つ辞書は、dataTypeNameキーの値がmeta_dataではない最初の辞書です。代わりに、値は文字列です。この辞書は、最終的なデータセットの最初の列に関する情報を示しています。この列の要素は、テキスト形式(つまり、文字列)です。この最初の辞書は、nameキーにDBNの値を持つため、DBNが最初の列の名前であることを示しています。この辞書に続くすべての辞書(columnsキー内)は、それらのdataTypeNameキーの値としてmeta_dataを持たないため、これらの辞書はDataFrameの次の列に関する情報を表しています。

次のステップでは、テーブルの列に関する情報を見つける方法の基本的な理解があるので、これらの列の名前を取得します。

カラム名を見つける

このセクションでは、APIエンドポイントから取得したすべての列の名前を、”columns”というリストに追加します。以下の行をJupyter Notebookの新しいセルに追加し、セルを実行してください。

データを変換するための「convert_data.ipynb」を作成してください。
  1. response=requests.get(‘https://data.cityofnewyork.us/api/views/ihfw-zy9j/rows.json’).json()
  2. columns=[]
  3. for i in response[‘meta’][‘view’][‘columns’]:
  4. if(i[‘dataTypeName’]==‘meta_data’):
  5. continue
  6. else:
  7. columns.append(i[‘name’])

 

ステップ2のメソッド3と同様に、requestsモジュールを使用してこのURLにあるデータを読み込み、変数responseに割り当てます。

3行目では、カラムのリストを定義します。5行目では、メタキーの値の中で定義されたビューキーの値の中で、カラムキーを定義します。

forループは、columnsキーに添付されたリスト内のすべての辞書を繰り返し処理し、それらの辞書のdataTypeNameキーの値を確認します。現在の辞書のdataTypeNameキーの値がmeta_dataと等しい場合、次の辞書に進みます。もし等しくない場合は、nameキーの値をcolumnsリストに追加します。

次に、列リストの内容をチェックしてください。新しいセルで次の行を実行してください。

データを変換するconvert_data.ipynb
columns

列の名前が画面に表示されます。

Output

[‘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’]

出力結果は、dataTypeNameがmeta_dataではない任意の列がcolumnsリストに追加されたことを確認しています。

このセクションでは、順不同のAPIエンドポイントからのカラム名のリストを取得し、最終的なDataFrameを作成するために必要となります。次に、カラムリストで定義されたカラムに属するデータを抽出します。

n個のサブリストを定義する

このセクションでは、API内の列の数を決定し、この数に対応するサブリストのリストを定義します。

最終的には、ステップ2のメソッド2を使用して、列名を示すキーと、それらのキーの値が各列の要素を表すリストである辞書からpandasのDataFrameを取得します。APIの列数を決定した後、同じ数のサブリストからなるリストを定義し、各サブリストには各列のデータが含まれます。

この操作を使用して辞書を定義したら、columnsのリストとサブリストのリストをループ処理することで、辞書に動的に追加することができます。たとえば、インデックス0のサブリストは、columnsリストのインデックス0の列名の要素のリストとして使用されます。同様に、インデックス1のサブリストは、columnsリストのインデックス1の列名の要素のリストとして使用されます。

前のステップでは、列の名前のリストを取得しました。次に、新しいセルでこの行を実行して、このリストの長さを確認します。

データを変換するためのconvert_data.ipynb
len(columns)

columnsのlen()は、columnsリスト内のアイテム数を返します。

APIに含まれる列の数が画面に表示されます。

Output

38

38列持っているので、38個のサブリストを定義し、それぞれのサブリストに各列のデータを含めます。

新しいセルで以下のコードを実行して、38のサブリスト(名前はd)を作成してください。

データの変換をするための convert_data.ipynbファイル
d = [[] for x in  range(len(columns))]

d

リストを作成するために、まずその名前をつけます(この場合、dとします)。データセット内の各配列([])は、さきほど見つけた38列の範囲からデータを含む新しいサブリストを作成します。

以下の出力は、38個のサブリストのリストを示しています。

Output

[[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []]

これらのサブリストは最初は空です。なぜなら、まだ要素を追加していないからです。

現在、リストd内には38のサブリストが作成されました。これらの38個のサブリストの内容は、38個の列のデータを表します。次に、その内容を追加します。

カラムの値を取得する

このセクションでは、APIのエンドポイントから列単位のデータを抽出し、前のステップで作成した38のサブリストにそのデータを追加します。これを行うには、まずデータキーがAPI全体でどこに存在するかを調べる必要があります。データキーの値は、テーブルの内容を表します。

ブラウザでAPIのURLにアクセスする際には、CTRL+Fを入力してデータを検索してください。検索結果は約73回見つかります。最後の出現箇所を見つけ、以下の内容が表示されます。

ニューヨークの学校スナップショットのURLからのAPIデータを示すデータ部分のサブリスト。
...
"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" ]
, [ "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" ]
, [ "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" ]
, [ "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" ]
, [ "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" ]
, [ "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" ]
, [ "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" ]
...

データキーに割り当てられたリスト内の各サブリストは、あなたの見込みのあるDataFrameの1行の値を示します。実際の行データが始まる場所を特定するためには、列の数とデータセクションの1つのサブリスト内の要素数を比較する必要があります。

新しいセルで以下のコードを実行して、列の数を確認してください。

データを変換するファイルの.ipynb拡張子
len(columns)

以下の出力は、列の数を表示します。

Output

38

次に、データ内の最初のサブリストの長さをチェックします。これは最初の行に含まれる値の数です。

データ変換.ipynb

len(response['data'][0])

データ内の最初のサブリストは、そのID番号が0で指定されます。

以下の出力は、データの最初のサブリストの要素数を表示します。

Output

46

データは行方向にあるので、最初のサブリストの要素数(46)は列数(38)と等しいと思うかもしれません。しかし、各サブリストの長さは46であり、38よりも8多いです。列のキー内には、dataTypeNameキーの値としてmeta_dataがある辞書が8つあることを思い出してください。したがって、これらのサブリストの先頭に見られる余分な8つの値はメタデータの値を示しており、テーブルの内容を表していません。

リストのインデックスは0から始まるため、0から7までの範囲にあるこれらのサブリストの値はDataFrameの内容を表していないことがわかりますが、メタデータの値を表しています。したがって、行単位のデータの内容はインデックス8から始まります。

新しいセルで次の行を実行して、データのサブリスト内の要素を46-38(8)のインデックスから46のインデックスまでのループを使用して追加します。これをテストするために、すべてのサブリストからデータを抽出する代わりに、最初の行からデータを抽出します。

データを変換するためのconvert_data.ipynb。
count=0

for i in response['data'][0][len(response['data'][0])-len(columns):len(response['data'][0])]: #from index 8 to 45

    d[count].append(i)

    count=count+1

d

この場合、変数countは、最初の行の列データをn番目のリストdの末尾に追加するのに役立ちます。

その後、コードはデータ内の最初のサブリストを反復処理して、インデックス8から45までの要素(38個の要素)を取得します。

response[‘data’][0]の長さは、データキー内の最初のサブリストの長さを表しており、len(columns)はリスト”columns”の要素数であり、最終的なDataFrameの列数を示しています。

最初の数回の繰り返しについての概要を以下に示します。カウントは最初に0です。forループに入ると、iはresponse[‘data’][0][8]であり、最初のサブリスト中の最初のメタデータ以外の値です。次に、このiの値をd[0]に追加します。角カッコ内の0は現在のカウントの値です。結果として、この値がリストd内の最初のサブリストに追加されます。

カウントは1ずつ増加します。iがresponse[‘data’][0][9](最初のサブリスト内での2番目のメタデータ以外の値)の場合、iの値をd[1]に追加します(countは前の反復で1増加したため、0は1になります)。その結果、この値はリストdの2番目のサブリストに追加されます。このプロセスは、インデックス45に到達するまで続きます。上記のコードの最後の行では、更新されたサブリストのリストdが表示されます。

出力には最初の行のデータが表示されます。

Output

[[’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のデータキーの値として使用されるリスト内の最初のサブリストと比較してください。

最初のサブリストの要素(NY学校スナップショットURLからのAPIデータ)
...
"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" ]
...

上のボックスの右側にスクロールして、完全なデータスニペットを表示する必要があるかもしれません。

最初のいくつかの値(インデックス0から7まで)は、メタデータ列に関連する情報を表しています。最初のサブリスト内の強調された値(インデックス8から45まで)は、抽出に成功した最初の行の値です。

すべての行に対して同じタスクを実行するためには、前のコードを更新する必要があります。まず、新しいセルで以下の行を実行して、38つのサブリストからなるdリストを再定義します。

データ変換.ipynb
d = [[] for x in  range(len(columns))]

あなたは、サブリストdのリストを再定義しています。現在、サブリストdは最初の行のすべての要素を含んでいます。今度は、同じ操作を最初の行を含むすべての残りの行に対して行いたいと考えています。

新しい38のサブリストのリストを作成したので、次の行を新しいセルで実行してください。この行は、将来のデータフレームの全行に対してデータ抽出を行います。

データ変換を行うための「convert_data.ipynb」を日本語で言い換える。
  1. for i in response[‘data’]:
  2. count=0
  3. for j in range(len(response[‘data’][0])len(columns),len(response[‘data’][0])):
  4. d[count].append(i[j])
  5. count+=1

 

1行目の「for i in response[‘data’]」では、i が各サブリストに順番に割り当てられていることを意味しています。

いくつかのイテレーションの概要を説明します。最初のサブリストをデータキーに割り当てたリストiから始まります。カウントは0です。

Pythonでは、Line 3を使用することで、すべてのサブリストのインデックス8から46までの要素を繰り返し処理できます。forループの上限はPythonでは排他的に扱われるため、インデックス8から45までの要素が取得されます。

次のように日本語で言い換えることができます:

“d[count].append(i[j])” は “d[0].append(i[8])” を意味し、つまり現在iに割り当てられている最初のサブリストのインデックス8の要素を、リストdの最初のサブリストに追加することを意味します。countは1増加します。あなたはまだ内部ループの中にいます。jは今9になります。

今、d[1].append(i[9])である。これは、最初のサブリスト(外側のループでiに割り当てられたまま)のインデックス9の要素が、リストdの2番目のサブリストに追加されることを意味する。カウントが増加する。内側のループは、1つの行のすべての値をdのすべてのサブリストに追加するまで続く。

内側のループの最後に、最初の行の最後の値を追加する操作は、次のようになります:d[37].append(i[45])。iの最初のイテレーションの終わりに、リストdは前の出力と同じようになります(dのすべてのサブリストには1つの要素しか含まれません)。

内側のループから抜け出すと、外側のループに移行します。iには、データキーに割り当てられたリスト内の次のサブリスト(2番目のサブリスト)が割り当てられます。count値は0に戻ります。

この2番目のiの反復で内部ループから抜けると、dのすべてのサブリストにはそれぞれ2つの値が含まれます。各サブリストの2番目の値は、2行目に属するデータを表します。これは、データキーに割り当てられたリスト内に存在するすべてのサブリストに適用されます。

dのサブリストの取得データがどのように見えるかをイメージするために、dの最初の3つのサブリストの最初の5つの要素を取得します。結果のデータフレームでは、これらの値は最初の3つの列の最初の5つの要素となります。

dのインデックス0のサブリストの最初の5つの要素を確認してから始めてください。

データを変換するためのconvert_data.ipynb
d[0][0:5]

出力結果は次のように表示されます。

Output

[’01M015′, ’01M015′, ’01M015′, ’01M015′, ’01M015′]

ブラウザで表示されるAPIのデータセクションと比較することで、出力を検証することができます。

最初のサブリストの要素(NY School Snapshot URLからのAPIデータ)
...
"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" ]
, [ "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" ]
, [ "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" ]
, [ "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" ]
, [ "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" ]
,
...

上のボックスの右にスクロールする必要があるかもしれません。完全なデータスニペットを閲覧するためです。

取得した値は、各サブリストのインデックス8にあるハイライトされた値と一致しています。これらのサブリストのインデックス0-7の要素はメタデータの値であり、将来的なデータフレームの値ではありません。最終的には、これらの値は列のインデックス0の最初の5つの要素を表します。

次に、dのインデックス1にあるサブリストの最初の5つの要素を確認することができます。

データを変換する.convert_data.ipynb
d[1][0:5]

第二のサブリストの最初の5つの要素が画面に表示されます。

Output

[‘P.S. 015 ROBERTO CLEMENTE’, ‘P.S. 015 ROBERTO CLEMENTE’, ‘P.S. 015 ROBERTO CLEMENTE’, ‘P.S. 015 ROBERTO CLEMENTE’, ‘P.S. 015 ROBERTO CLEMENTE’]

これらの値は、カラムリストのインデックス1の列「名前」の最初の5つの要素を表しています。APIのURLのデータセクションで出力を確認してください。

第二のサブリストの要素(NY School Snapshot URLからのAPIデータ)
...
"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" ]
, [ "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" ]
, [ "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" ]
, [ "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" ]
, [ "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" ]
,
...

上のボックスの右にスクロールして、完全なデータスニペットを表示する必要があるかもしれません。取得した値は、ハイライトされた値と一致しています。

最後に、dのインデックス2のサブリストの最初の5つの要素を確認してください。

データを変換する。
d[2][0:5]

以下の出力は画面に表示されます。

Output

[‘20052006’, ‘20062007’, ‘20072008’, ‘20082009’, ‘20092010’]

APIのURLのデータセクションで出力を確認してください。

ニューヨーク学校スナップショットのURLからのAPIデータのセカンドサブリストの要素
...
"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" ]
, [ "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" ]
, [ "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" ]
, [ "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" ]
, [ "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" ]
,
...

上のボックスの右にスクロールして、完全なデータスニペットを表示する必要があるかもしれません。取得した値はハイライトされた値と一致しています。これらの値は、カラムリストのインデックス2のカラムであるschoolyearの最初の5つの要素を表しています。

このステップの最後に到達すると、38個の列すべてのすべての行のデータが正常に取り出され、それらがリストdの38個のサブリストに追加されます。今度は、これまでに取得したデータを使用して、最終ステップでPandasのDataFrameを作成する準備ができました。

データフレームのための辞書を作成する

このステップでは、38列のそれぞれの名前と値を抽出しました。これらは辞書形式のパンダスのデータフレームに渡すことになります。このセクションでは、キーが列名(リスト「columns」から)で、値がdから取得した38個のサブリストになる辞書を作成します。

新しいセルで次のコードを実行してください。

データを変換するファイル「convert_data.ipynb」
json_dict={}

for i in  range(0,len(columns)):
	json_dict.update({columns[i]:d[i]})

(以下の文を日本語で表現する):
0から38までの範囲をループし、最終的な辞書json_dictにキーと値のペアを追加し、pandasのデータフレームへの変換に使用します。例えば、iが0の場合、dのインデックス0のサブリストを値として、キーDBN(columns[0]で表される)に割り当てます。この操作は、残りのインデックスに対しても同様に行われます。

辞書の取得したキーの表示方法を把握するために、json_dictに存在するすべてのキーを確認してください。

データを変換する、convert_data.ipynb。
json_dict.keys()

最終的な辞書のキーのリストが画面に表示されます。 (Saishūtekina jisho no kī no risuto ga gamen ni hyōji sa re masu.)

Output

dict_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”という名前を使用しています)。

データの変換を行うための convert_data.ipynb。
data=pd.DataFrame(json_dict)

次に、結果のデータフレームの一部を確認してください。 (Tsugi ni, kekka no deeta fureemu no ichibu o kakunin shite kudasai.)

以下のファイル、convert_data.ipynbを日本語で言い換えます。

「コンバートデータ.ipynb」というファイルを変換してください。

data.head()

データフレームの最初の5行が画面に表示されます。

Output

DBN 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 0 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 1 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 2 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 3 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 4 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から渡すことで、DataFrameを成功裏に作成しました。

結論

このチュートリアルでは、さまざまな形式の辞書やURLからpandasのDataFrameを作成するための一般的な方法を使いました。また、列とそれに対応する値が直感的に表示されないAPIエンドポイントからのDataFrameも作成しました。

このチュートリアルは、通常のAPIエンドポイントや辞書から抽出したデータを使用して、ユニークな方法でDataFramesを作成する方法を理解するのに役立ちます。pandasのDataFramesについてもっと知りたい方は、当社のpandasチュートリアルをご覧ください。

コメントを残す 0

Your email address will not be published. Required fields are marked *