8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Fringe81Advent Calendar 2019

Day 12

PythonユーザーがJSONファイルを渡す時の話

Posted at

Fringe81 Advent Calendar 2019、12日目の記事です。

今回は(僕みたいな)Pythonしか触ったことない人が実務で必要になるであろう小ネタを書きます。タイトルの通り、データをPythonでゴニョゴニョした後、フロントエンジニアの人にJSONファイルでデータを渡す時の話です。

データの準備

例えば新入社員の自己紹介用の画面を作りたい!という時に、以下のような形でデータが欲しいと言われたとします(それぞれのデータはCSVファイルみたいなので個別にあったとします)。

interface Member {
    id: string;
    name: string;
    profile: {
        age: number;
        height: number;
        weight: number:
    };
    likes: {
        name: string;
        reason: string;
    }[];
}[];

これをPythonしか使えない新米はpandasで整理してアウトプットできないかと考えます。まずはデータを準備します。

import pandas as pd

# 以下のデータは別々にファイルが存在し、それをpandasで読み込んだ状態と一致するものとする
df1 = pd.DataFrame(
    {
        "id": ["01", "02", "03"],
        "name": ["Aさん", "Bさん", "Cさん"]
    }
)
df2 = pd.DataFrame(
    {
        "id": ["01", "02", "03"],
        "age": [22, 24, 27],
        "height": [177, 171, 167],
        "weight": [64, 57, 62]
    }
)
df3 = pd.DataFrame(
    {
        "id": ["01", "02", "03"],
        "name": ["寿司・ゴルフ", "野球・カメラ", "アヒル・村人・戦士"],
        "reason": ["美味いから・スカッとするから", "盛り上がるから・記憶に残したいから", "可愛いから・親切だから・カッコいいから"]
    }
)

データの中身はこんな感じです。

df1
id name
0 01 Aさん
1 02 Bさん
2 03 Cさん
df2
id age height weight
0 01 22 177 64
1 02 24 171 57
2 03 27 167 62
df3
id name reason
0 01 寿司・ゴルフ 美味いから・スカッとするから
1 02 野球・カメラ 盛り上がるから・記憶に残したいから
2 03 アヒル・村人・戦士 可愛いから・親切だから・カッコいいから

データの整形

続いて、データの整形をしていきます。とりあえず形を整えつつ、一つのデータフレームにまとめます。

# df2の整形
# "profile"というカラムに辞書にまとめたものを入力
df2["profile"] = df2.apply(lambda row: {"age": row["age"], "height": row["height"], "weight": row["weight"]}, axis=1)
df2 = df2[["id", "profile"]]

# df3の整形
# 「・」で区切られているテキストを分割し、リスト型に内包させる
# "likes"というカラムに辞書にまとめたものを入力
df3["name"] = df3["name"].str.split("")
df3["reason"] = df3["reason"].str.split("")
df3["likes"] = df3.apply(lambda row: [{"name": name, "reason": reason} for name, reason in zip(row["name"], row["reason"])], axis=1)
df3 = df3[["id", "likes"]]

# データの結合
df = df1.merge(df2, on="id").merge(df3, on="id")

中身はこんな感じです。

df
id name profile likes
0 01 Aさん {'age': 22, 'height': 177, 'weight': 64} [{'name': '寿司', 'reason': '美味いから'}, {'name': '...
1 02 Bさん {'age': 24, 'height': 171, 'weight': 57} [{'name': '野球', 'reason': '盛り上がるから'}, {'name':...
2 03 Cさん {'age': 27, 'height': 167, 'weight': 62} [{'name': 'アヒル', 'reason': '可愛いから'}, {'name': ...

データの出力

最後にデータをJSONファイルに書き出します。

import json

# アウトプット用のdictを作成
# orientはリスト内の入れ子構造をそのまま保存できるように設定(ここの引数が重要)
output = df.to_dict(orient="records")

# 保存先のファイルを開いてデータを記入。
with open("introduction.json", "w") as f:
    # indentはファイルの中身が見やすいように設定
    # ensure_asciiは日本語の文字化けが起きないように設定
    json.dump(output, f, indent=4, ensure_ascii=False)

ちなみ中身はこんな感じになってるはずです。

output
[{'id': '01',
  'name': 'Aさん',
  'profile': {'age': 22, 'height': 177, 'weight': 64},
  'likes': [{'name': '寿司', 'reason': '美味いから'},
   {'name': 'ゴルフ', 'reason': 'スカッとするから'}]},
 {'id': '02',
  'name': 'Bさん',
  'profile': {'age': 24, 'height': 171, 'weight': 57},
  'likes': [{'name': '野球', 'reason': '盛り上がるから'},
   {'name': 'カメラ', 'reason': '記憶に残したいから'}]},
 {'id': '03',
  'name': 'Cさん',
  'profile': {'age': 27, 'height': 167, 'weight': 62},
  'likes': [{'name': 'アヒル', 'reason': '可愛いから'},
   {'name': '村人', 'reason': '親切だから'},
   {'name': '戦士', 'reason': 'カッコいいから'}]}]

以上です。これとは別に、dict型だけでまとめた方がやり易いかもしれませんが、今回はpandasのデータフレームで読み込んだものをそのまま変換する方法を書きました。

最後に

最後まで読んでいただきありがとうございました。次回はデザイナーのmirinrinです!引き続きFringe81 Advent Calendar 2019をお楽しみください。

8
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?