pandasのDataFrame作成

とりあえず冒頭にはこうして

import pandas as pd

ファイルから読み込む

csvやテキストはもちろんのこと圧縮ファイルからも読み込める

# csvファイル(,区切り)
df = pd.read_csv("myfile.csv")

# タブ区切りファイル
df = pd.read_csv("myfile.tsv", sep="\t") # pd.read_table(filename)でも同じ

# スペース区切りファイル
df = pd.read_csv("myfile.txt", delim_whitespace=True) # タブも区切り扱いになる

# 圧縮されたファイル
df = pd.read_csv("myfile.zip", compression="infer") # ファイル名(拡張子)から圧縮方式がわからなければ"zip"など指定する。


# その他使えそうなオプション引数たち
# 読み込み方法指定系
encoding = "utf-8" # エンコード指定
dtype = {<列名or列番号>:int, ...} # 列ごとの型指定
header = None # ヘッダなし(デフォルトは1行目がヘッダになる)
names = ["列A","列B", "列C"]  # 列名指定
index_col = 1 # 1列目をインデックスにする(リストで複数渡せばマルチインデックス)
error_bad_lines = False, warn_bad_lines = True # 項目が多い行があってもエラー出さず読み込み警告だけだす

#軽くデータ変換系
converters = {<列名or列番号>:<Callable>, ...} # 各列に対する前処理
skipinitialspace = True # 区切り文字直後の空白を無視
true_values = ["yes", "great!"] # yesと great!はTrueとして読み込む
false_values = ["no", "bad"] # noとbadはFalseとして読み込む
na_values = ["どちらでもない"] # 「どちらでもない」は欠損値(nan)として読み込む
keep_default_na = False # 空白などを欠損値扱いしない
parse_dates = ["列A"] # 列Aは日付型として読み込む
parse_dates = [["列y", "列m", "列d"]] # y年m月d日という日付としてまとめて読み込む(年月日が別カラムに入ってるケース)
parse_dates = True # インデックスを日付データとして読み込む
date_parser = lambda x: datetime.strptime(x, "%Y=%m=%d") # 2021=10=10みたいな変な書式を読み込む

# 読み込み位置指定系
usecols = ["列B", "列D"] # 列Bと列Dだけ読み込む。ラムダ式も渡せる。
skiprows = 10 # 10行目まで読み飛ばす
skiprows = [3,6,8] # 3,6,8行目を読み飛ばす
skipfooter = 20 # 最後から20行は読まない
nrow = 30 # 30行だけ読む
comment = "#" # 行頭が#で始まってる行はコメント扱いで読み飛ばす
skip_blank_lines = True # 空白行を読み飛ばす

# 他省略

ファイルからの読み込みはこれだけ把握してればほぼ好きなことができるんじゃないかな。

データから作成する

2次元リスト等から作成

2次元リストやタプル、numpyのndarrayみたいな配列っぽいものからもDataFrameを作成可能。

import numpy as np

array = [[1, 2, 3],
        [4, 5, 6],
        [7, 8, 9, 10]]

# 列名とインデックス名、データ型を指定可。指定しなければ連番になる。
df = pd.DataFrame(array,
                columns=["あ", "い", "う", "え"],
                index=["A", "B", "C"],
                dtype=np.float64)
print(df)

結果

     あ    い    う     え
A  1.0  2.0  3.0   NaN
B  4.0  5.0  6.0   NaN
C  7.0  8.0  9.0  10.0

足りないところは欠損値扱いになる。

行にはindexで指定した名前、列にはcolumnsで指定した名前がついてることがわかる。(表示ずれてるけど)

データ型の指定はfloatなどPython組み込み型でも可。

辞書から作成

{列名:[値のリスト],…}という辞書からも作成可能。

df = pd.DataFrame({"列A":[1,2,3],
                   "列B":[4,5,6],
                   "列C":[7,8,9]})
print(df)

結果

   列A  列B  列C
0   1   4   7
1   2   5   8
2   3   6   9

この場合は各キーの長さが違うとエラーになるので注意。

辞書のリストから作成

あんま使ったことないけど、{列名:値}という辞書のリストになってる場合でもそのまま生成可能。

dict_list = [{"name": "john", "age": 20, "job": "engineer"},
                {"name": "Elica", "age": 35, "job": "director"},
                {"name": "Bread", "age": 82, "job": "assassin"}]
df = pd.DataFrame(dict_list, index=[10, 20, 30])
print(df)

結果

     name  age       job
10   john   20  engineer
20  Elica   35  director
30  Bread   82  assassin

まぁいずれも感覚的にわかりやすいので使いやすいかと。

おそらくこれはAPIの返り値などで使うケースが多いんじゃないかと。

もっと複雑なケースで辞書が入れ子になってる場合はpandas.json_normalizeというのを使ってみるとよし。

dict_list = [{"name":"john", "age":20, "job":{ "main":"engineer", "sub":"corder"}},
             {"name":"Elica", "age":35, "job":{"main":"director", "sub":"officer"}},
             {"name":"Bread", "age":82, "job":{"main":"assassin", "sub":"hangman"}}]
df = pd.DataFrame(pd.json_normalize(dict_list, sep="_"))
print(df)

結果

    name  age  job_main  job_sub
0   john   20  engineer   corder
1  Elica   35  director  officer
2  Bread   82  assassin  hangman

sepは指定しなければ .(ピリオド)が使われる。

より複雑な場合は下記参照

参考リンク:pandasのjson_normalizeで辞書のリストをDataFrameに変換 | note.nkmk.me

python

Posted by gran-gran-gran