Open In Colab

Pandasの使い方 (基礎)

Pandasは、データ分析のためのライブラリで
統計量を計算・表示したり、それらをグラフとして可視化出来たり
前処理などの地道だが重要な作業を比較的簡単に行うことができる。

まずはインポートしよう。pdという名前で使うのが慣例。

import pandas as pd 

pandasでは主にSeriesDataFrameの2つのオブジェクトを扱う。
SeriesDataFrameの特殊な場合とみなせるので、以下ではDataFrameのみ説明することにします。

DataFrame型

DataFrameはExcelシートのような二次元のデータを表現するのに利用され各種データ分析などで非常に役に立つ。

from pandas import DataFrame

以下の辞書型をDataFrameのオブジェクトに変換してみましょう。

data = { '名前': ["Aさん", "Bさん", "Cさん", "Dさん", "Eさん"],
        '出身都道府県':['Tokyo', 'Tochigi', 'Hokkaido','Kyoto','Tochigi'],
        '生年': [ 1998, 1993,2000,1989,2002],
        '身長': [172, 156, 162, 180,158]}
df = DataFrame(data)
print("dataの型", type(data))
print("dfの型",type(df))
dataの型 <class 'dict'>
dfの型 <class 'pandas.core.frame.DataFrame'>

jupyter環境でDataFrameをコードセルの最終行に書くと、”いい感じ”に表示してくれる

df
名前 出身都道府県 生年 身長
0 Aさん Tokyo 1998 172
1 Bさん Tochigi 1993 156
2 Cさん Hokkaido 2000 162
3 Dさん Kyoto 1989 180
4 Eさん Tochigi 2002 158

printだとちょっと無機質な感じに。

print(df)
    名前    出身都道府県    生年   身長
0  Aさん     Tokyo  1998  172
1  Bさん   Tochigi  1993  156
2  Cさん  Hokkaido  2000  162
3  Dさん     Kyoto  1989  180
4  Eさん   Tochigi  2002  158

単一のコードセルの途中でDataFrameを表示したい場合などは、display関数を使うと良い。

display(df)
名前 出身都道府県 生年 身長
0 Aさん Tokyo 1998 172
1 Bさん Tochigi 1993 156
2 Cさん Hokkaido 2000 162
3 Dさん Kyoto 1989 180
4 Eさん Tochigi 2002 158

info()関数を作用させると、詳細な情報が得られる。
列ごとにどんな種類のデータが格納されているのかや、 メモリ使用量など表示することができる。

df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5 entries, 0 to 4
Data columns (total 4 columns):
 #   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
 0   名前      5 non-null      object
 1   出身都道府県  5 non-null      object
 2   生年      5 non-null      int64 
 3   身長      5 non-null      int64 
dtypes: int64(2), object(2)
memory usage: 292.0+ bytes

DataFrameの要素を確認・指定する方法

index: 行方向のデータ項目(おもに整数値(行番号),ID,名前など)
columns: 列方向のデータの項目(おもにデータの種類)
をそれぞれ表示してみよう。

df.index
RangeIndex(start=0, stop=5, step=1)
df.columns
Index(['名前', '出身都道府県', '生年', '身長'], dtype='object')

行方向を、整数値(行数)ではなく名前にしたければ

data1 = {'出身都道府県':['Tokyo', 'Tochigi', 'Hokkaido','Kyoto','Tochigi'],
        '生年': [ 1998, 1993,2000,1989,2002],
        '身長': [172, 156, 162, 180,158]}
df = DataFrame(data1)
df.index =["Aさん", "Bさん", "Cさん", "Dさん", "Eさん"]
df
出身都道府県 生年 身長
Aさん Tokyo 1998 172
Bさん Tochigi 1993 156
Cさん Hokkaido 2000 162
Dさん Kyoto 1989 180
Eさん Tochigi 2002 158

などとしてもよい。

特定の列を取得したい場合

df["身長"]
Aさん    172
Bさん    156
Cさん    162
Dさん    180
Eさん    158
Name: 身長, dtype: int64

と列名を指定すればよい。
以下の方法でも取得できるが、この授業では非推奨とする。

df.身長
Aさん    172
Bさん    156
Cさん    162
Dさん    180
Eさん    158
Name: 身長, dtype: int64

値のリスト(正確にはnumpy.ndarray型)として取得したければ

df["身長"].values
array([172, 156, 162, 180, 158])
df["出身都道府県"].values
array(['Tokyo', 'Tochigi', 'Hokkaido', 'Kyoto', 'Tochigi'], dtype=object)

などとすればよい。

慣れ親しんだ形に変換したければ、リストに変換すればよい

list(df["出身都道府県"].values)
['Tokyo', 'Tochigi', 'Hokkaido', 'Kyoto', 'Tochigi']

ある列が特定のものに一致するもののみを抽出するのも簡単にできる

df[df["出身都道府県"]=="Tochigi"]
出身都道府県 生年 身長
Bさん Tochigi 1993 156
Eさん Tochigi 2002 158

これは

df["出身都道府県"]=="Tochigi"
Aさん    False
Bさん     True
Cさん    False
Dさん    False
Eさん     True
Name: 出身都道府県, dtype: bool

が条件に合致するかどうかTrue/Falseの配列(正確にはSeries)になっていて、
df[ [True/Falseの配列] ]とすると、Trueに対応する要素のみを返すフィルターのような役割になっている。

列の追加

#スカラー値の場合"初期化"のような振る舞いをする
df["血液型"] = "A"
df
出身都道府県 生年 身長 血液型
Aさん Tokyo 1998 172 A
Bさん Tochigi 1993 156 A
Cさん Hokkaido 2000 162 A
Dさん Kyoto 1989 180 A
Eさん Tochigi 2002 158 A
df["血液型"] = "B"
df
出身都道府県 生年 身長 血液型
Aさん Tokyo 1998 172 B
Bさん Tochigi 1993 156 B
Cさん Hokkaido 2000 162 B
Dさん Kyoto 1989 180 B
Eさん Tochigi 2002 158 B

リストやnumpy.ndarrayを列として追加することができる。

#リストで追加
df["血液型"] = [ "A", "O","AB","B","A"]
df
出身都道府県 生年 身長 血液型
Aさん Tokyo 1998 172 A
Bさん Tochigi 1993 156 O
Cさん Hokkaido 2000 162 AB
Dさん Kyoto 1989 180 B
Eさん Tochigi 2002 158 A

特定の行を取得したい場合

たとえば、行番号がわかっているなら、iloc関数を使えば良い

df.iloc[3]
出身都道府県    Kyoto
生年         1989
身長          180
血液型           B
Name: Dさん, dtype: object

値のみ取得したければ先程と同様valuesnumpy.ndarrayを取得できる

df.iloc[3].values
array(['Kyoto', 1989, 180, 'B'], dtype=object)

また、以下のような使い方もできるが

df[1:4] 
出身都道府県 生年 身長 血液型
Bさん Tochigi 1993 156 O
Cさん Hokkaido 2000 162 AB
Dさん Kyoto 1989 180 B

df[1]といった使い方は出来ず、KeyErrorが発生する、

df[1]
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
File ~/.pyenv/versions/3.11.4/lib/python3.11/site-packages/pandas/core/indexes/base.py:3805, in Index.get_loc(self, key)
   3804 try:
-> 3805     return self._engine.get_loc(casted_key)
   3806 except KeyError as err:

File index.pyx:167, in pandas._libs.index.IndexEngine.get_loc()

File index.pyx:196, in pandas._libs.index.IndexEngine.get_loc()

File pandas/_libs/hashtable_class_helper.pxi:7081, in pandas._libs.hashtable.PyObjectHashTable.get_item()

File pandas/_libs/hashtable_class_helper.pxi:7089, in pandas._libs.hashtable.PyObjectHashTable.get_item()

KeyError: 1

The above exception was the direct cause of the following exception:

KeyError                                  Traceback (most recent call last)
Cell In[24], line 1
----> 1 df[1]

File ~/.pyenv/versions/3.11.4/lib/python3.11/site-packages/pandas/core/frame.py:4102, in DataFrame.__getitem__(self, key)
   4100 if self.columns.nlevels > 1:
   4101     return self._getitem_multilevel(key)
-> 4102 indexer = self.columns.get_loc(key)
   4103 if is_integer(indexer):
   4104     indexer = [indexer]

File ~/.pyenv/versions/3.11.4/lib/python3.11/site-packages/pandas/core/indexes/base.py:3812, in Index.get_loc(self, key)
   3807     if isinstance(casted_key, slice) or (
   3808         isinstance(casted_key, abc.Iterable)
   3809         and any(isinstance(x, slice) for x in casted_key)
   3810     ):
   3811         raise InvalidIndexError(key)
-> 3812     raise KeyError(key) from err
   3813 except TypeError:
   3814     # If we have a listlike key, _check_indexing_error will raise
   3815     #  InvalidIndexError. Otherwise we fall through and re-raise
   3816     #  the TypeError.
   3817     self._check_indexing_error(key)

KeyError: 1

より複雑な行・列の抽出

上にならって、2000年より前に生まれた人だけを抽出し

df[ df["生年"] < 2000 ]
出身都道府県 生年 身長 血液型
Aさん Tokyo 1998 172 A
Bさん Tochigi 1993 156 O
Dさん Kyoto 1989 180 B

さらにこのうち身長が170cm以上の人だけがほしければ

df[(df["生年"] < 2000) & (df["身長"]>170)]
出身都道府県 生年 身長 血液型
Aさん Tokyo 1998 172 A
Dさん Kyoto 1989 180 B

などとすればよい。複数条件の場合は、条件を()で囲む必要があることに注意しよう。

他にもiloc,locなどを用いれば、特定の行・列を抽出することができる

  • ilocは番号の指定のみに対応

  • locは名前(列名・行明)のみ

欲しい要素の数値もしくは項目名のリストを行・列のそれぞれについて指定してやればよい。

df.iloc[[0], [0]] #0行目,0列目
出身都道府県
Aさん Tokyo
#スライスで指定することもできる
df.iloc[1:4, :3] #1-3行目かつ0-2列目 (スライスの終点は含まれないことに注意)
#スライスの場合は、 1:4が[1,2,3]と同じ働きをするので、括弧[]はいらない
出身都道府県 生年 身長
Bさん Tochigi 1993 156
Cさん Hokkaido 2000 162
Dさん Kyoto 1989 180

locを使う場合は、indexの代わりに項目名で指定する。

df.loc[["Aさん","Cさん"],["出身都道府県","身長"]] 
出身都道府県 身長
Aさん Tokyo 172
Cさん Hokkaido 162

スライス的に指定することもできる

df.loc["Bさん":"Dさん","出身都道府県":"生年"]
出身都道府県 生年
Bさん Tochigi 1993
Cさん Hokkaido 2000
Dさん Kyoto 1989

といった具合。

locを使う場合、1:4や[1,2,3,4]はindexのスライスではなく、
項目名を意味し、Eさんのデータも含まれている事がわかる。

Webページにある表をDataFrameとして取得する

pandas内のread_html関数を用いれば、
Webページの中にある表をDataFrame形式で取得することもできます。

以下では例としてWikipediaのノーベル物理学賞のページにある、受賞者一覧を取得してみましょう

url = "https://ja.wikipedia.org/wiki/%e3%83%8e%e3%83%bc%e3%83%99%e3%83%ab%e7%89%a9%e7%90%86%e5%ad%a6%e8%b3%9e"
tables = pd.read_html(url)

表の数を数えてみると…

print(len(tables))
18

ページ内に、18個もの表があることがわかります。(ほとんどはwikipediaのテンプレート等)

たとえば、2010年代の受賞者のみに興味がある場合は

df = tables[12]
df
年度 受賞者名 受賞者名.1 国籍 受賞理由[4]・原著ないし関連論文
0 2010年 NaN アンドレ・ガイム Andre Geim オランダ ( ロシア出身) 二次元物質グラフェンに関する革新的実験[注 71]
1 2010年 NaN コンスタンチン・ノボセロフ Konstantin Novoselov ロシア イギリス 二次元物質グラフェンに関する革新的実験[注 71]
2 2011年 NaN ソール・パールマッター Saul Perlmutter アメリカ合衆国 遠方の超新星の観測を通した宇宙の加速膨張の発見 Astrophys. J.: 517 (19...
3 2011年 NaN ブライアン・P・シュミット Brian Schmidt オーストラリア アメリカ合衆国 遠方の超新星の観測を通した宇宙の加速膨張の発見 Astrophys. J.: 517 (19...
4 2011年 NaN アダム・リース Adam Riess アメリカ合衆国 遠方の超新星の観測を通した宇宙の加速膨張の発見 Astrophys. J.: 517 (19...
5 2012年 NaN セルジュ・アロシュ Serge Haroche フランス ( モロッコ出身) 個別の量子系に対する計測および制御[注 72]を可能にする画期的な実験的手法に関する業績[5...
6 2012年 NaN デービッド・ワインランド David J. Wineland アメリカ合衆国 個別の量子系に対する計測および制御[注 72]を可能にする画期的な実験的手法に関する業績[5...
7 2013年 NaN フランソワ・アングレール François Englert ベルギー 欧州原子核研究機構 (CERN) によって存在が確認された素粒子(ヒッグス粒子)に基づく、質...
8 2013年 NaN ピーター・ヒッグス Peter Higgs イギリス 欧州原子核研究機構 (CERN) によって存在が確認された素粒子(ヒッグス粒子)に基づく、質...
9 2014年 NaN 赤﨑勇 Isamu Akasaki 日本 高輝度で省電力の白色光源を実現可能にした青色発光ダイオードの発明[10]
10 2014年 NaN 天野浩 Hiroshi Amano 日本 高輝度で省電力の白色光源を実現可能にした青色発光ダイオードの発明[10]
11 2014年 NaN 中村修二 Shuji Nakamura アメリカ合衆国 ( 日本出身) 高輝度で省電力の白色光源を実現可能にした青色発光ダイオードの発明[10]
12 2015年 NaN 梶田隆章 Takaaki Kajita 日本 素粒子「ニュートリノ」が質量を持つことを示すニュートリノ振動の発見[11] Nucl. Ph...
13 2015年 NaN アーサー・B・マクドナルド Arthur B. McDonald カナダ 素粒子「ニュートリノ」が質量を持つことを示すニュートリノ振動の発見[11] Nucl. Ph...
14 2016年 NaN デイヴィッド・J・サウレス David J. Thouless イギリス アメリカ合衆国 物質のトポロジカル相とトポロジカル相転移の理論的発見[12][13]
15 2016年 NaN ダンカン・ホールデン Duncan Haldane イギリス スロベニア 物質のトポロジカル相とトポロジカル相転移の理論的発見[12][13]
16 2016年 NaN ジョン・M・コステリッツ Michael Kosterlitz イギリス アメリカ合衆国 物質のトポロジカル相とトポロジカル相転移の理論的発見[12][13]
17 2017年 NaN レイナー・ワイス Rainer Weiss アメリカ合衆国 ( ドイツ出身) LIGO検出器および重力波の観測への決定的な貢献
18 2017年 NaN バリー・バリッシュ Barry Barish アメリカ合衆国 LIGO検出器および重力波の観測への決定的な貢献
19 2017年 NaN キップ・ソーン Kip Thorne アメリカ合衆国 LIGO検出器および重力波の観測への決定的な貢献
20 2018年 NaN アーサー・アシュキン Arthur Ashkin アメリカ合衆国 光ピンセットの開発と生体システムへの応用
21 2018年 NaN ジェラール・ムル Gérard Mourou フランス 超高出力・超短パルスレーザーの生成方法の開発
22 2018年 NaN ドナ・ストリックランド Donna Strickland カナダ 超高出力・超短パルスレーザーの生成方法の開発
23 2019年 NaN ジェームズ・ピーブルス Jim Peebles アメリカ合衆国 ( カナダ出身) 物理宇宙論における理論的発見
24 2019年 NaN ミシェル・マイヨール Michel Mayor スイス 太陽型恒星を周回する太陽系外惑星の発見
25 2019年 NaN ディディエ・ケロー Didier Queloz スイス 太陽型恒星を周回する太陽系外惑星の発見

Pandasでcsv/Excelファイルを読み込む

csvファイルの読み込み

pandasには、csvを読み込むための関数read_csvが用意されていて、ファイルパスを指定する他に、URLを指定して開く事ができる。

教育用標準データセットの一つであるSSDSE-B(県別推移)を読み込んでみよう。

下を実行すると…実はエラーとなる。

pd.read_csv("https://www.nstac.go.jp/sys/files/SSDSE-B-2024.csv")
---------------------------------------------------------------------------
UnicodeDecodeError                        Traceback (most recent call last)
Cell In[4], line 1
----> 1 pd.read_csv("https://www.nstac.go.jp/sys/files/SSDSE-B-2024.csv")

File /usr/local/lib/python3.10/site-packages/pandas/io/parsers/readers.py:948, in read_csv(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, date_format, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, on_bad_lines, delim_whitespace, low_memory, memory_map, float_precision, storage_options, dtype_backend)
    935 kwds_defaults = _refine_defaults_read(
    936     dialect,
    937     delimiter,
   (...)
    944     dtype_backend=dtype_backend,
    945 )
    946 kwds.update(kwds_defaults)
--> 948 return _read(filepath_or_buffer, kwds)

File /usr/local/lib/python3.10/site-packages/pandas/io/parsers/readers.py:611, in _read(filepath_or_buffer, kwds)
    608 _validate_names(kwds.get("names", None))
    610 # Create the parser.
--> 611 parser = TextFileReader(filepath_or_buffer, **kwds)
    613 if chunksize or iterator:
    614     return parser

File /usr/local/lib/python3.10/site-packages/pandas/io/parsers/readers.py:1448, in TextFileReader.__init__(self, f, engine, **kwds)
   1445     self.options["has_index_names"] = kwds["has_index_names"]
   1447 self.handles: IOHandles | None = None
-> 1448 self._engine = self._make_engine(f, self.engine)

File /usr/local/lib/python3.10/site-packages/pandas/io/parsers/readers.py:1723, in TextFileReader._make_engine(self, f, engine)
   1720     raise ValueError(msg)
   1722 try:
-> 1723     return mapping[engine](f, **self.options)
   1724 except Exception:
   1725     if self.handles is not None:

File /usr/local/lib/python3.10/site-packages/pandas/io/parsers/c_parser_wrapper.py:93, in CParserWrapper.__init__(self, src, **kwds)
     90 if kwds["dtype_backend"] == "pyarrow":
     91     # Fail here loudly instead of in cython after reading
     92     import_optional_dependency("pyarrow")
---> 93 self._reader = parsers.TextReader(src, **kwds)
     95 self.unnamed_cols = self._reader.unnamed_cols
     97 # error: Cannot determine type of 'names'

File parsers.pyx:579, in pandas._libs.parsers.TextReader.__cinit__()

File parsers.pyx:668, in pandas._libs.parsers.TextReader._get_header()

File parsers.pyx:879, in pandas._libs.parsers.TextReader._tokenize_rows()

File parsers.pyx:890, in pandas._libs.parsers.TextReader._check_tokenize_status()

File parsers.pyx:2050, in pandas._libs.parsers.raise_parser_error()

UnicodeDecodeError: 'utf-8' codec can't decode byte 0x94 in position 748: invalid start byte

その原因は、ファイルの文字コードがShift-JISであるため。 デフォルトのutf-8以外で作成されたファイルを読み込む場合、エンコーディングを指定する必要がある。

“shift_jis”等としたいところだが、最近のShift-JISに対応するエンコーディングの指示は”cp932”である。

df = pd.read_csv("https://www.nstac.go.jp/sys/files/SSDSE-B-2024.csv", encoding="cp932")
df
SSDSE-B-2024 Code Prefecture A1101 A110101 A110102 A1102 A110201 A110202 A1301 ... L322101 L322102 L322103 L322104 L322105 L322106 L322107 L322108 L322109 L322110
0 年度 地域コード 都道府県 総人口 総人口(男) 総人口(女) 日本人人口 日本人人口(男) 日本人人口(女) 15歳未満人口 ... 食料費(二人以上の世帯) 住居費(二人以上の世帯) 光熱・水道費(二人以上の世帯) 家具・家事用品費(二人以上の世帯) 被服及び履物費(二人以上の世帯) 保健医療費(二人以上の世帯) 交通・通信費(二人以上の世帯) 教育費(二人以上の世帯) 教養娯楽費(二人以上の世帯) その他の消費支出(二人以上の世帯)
1 2021 R01000 北海道 5183000 2446000 2737000 5147000 2429000 2717000 544000 ... 71448 22013 26676 9912 8816 13788 30483 9913 23762 51583
2 2020 R01000 北海道 5224614 2465088 2759526 5151366 2429697 2721669 555804 ... 77680 27305 27309 12255 9227 14251 41407 9394 26539 56316
3 2019 R01000 北海道 5259000 2480000 2780000 5223000 2464000 2759000 565000 ... 72912 20862 26332 9895 10466 16466 42277 8848 29335 57289
4 2018 R01000 北海道 5293000 2495000 2798000 5262000 2482000 2780000 577000 ... 69044 19089 27012 8845 11517 11437 39308 10825 26991 56984
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
596 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
597 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
598 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
599 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
600 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

601 rows × 112 columns

今の場合ファイルの(0から数えて)1行目にヘッダ(列名)にしたい情報があるのでheaderオプションを指定する。

url = "https://www.nstac.go.jp/sys/files/SSDSE-B-2024.csv"
df = pd.read_csv(url, encoding="cp932", header=1)
df
年度 地域コード 都道府県 総人口 総人口(男) 総人口(女) 日本人人口 日本人人口(男) 日本人人口(女) 15歳未満人口 ... 食料費(二人以上の世帯) 住居費(二人以上の世帯) 光熱・水道費(二人以上の世帯) 家具・家事用品費(二人以上の世帯) 被服及び履物費(二人以上の世帯) 保健医療費(二人以上の世帯) 交通・通信費(二人以上の世帯) 教育費(二人以上の世帯) 教養娯楽費(二人以上の世帯) その他の消費支出(二人以上の世帯)
0 2021.0 R01000 北海道 5183000.0 2446000.0 2737000.0 5147000.0 2429000.0 2717000.0 544000.0 ... 71448.0 22013.0 26676.0 9912.0 8816.0 13788.0 30483.0 9913.0 23762.0 51583.0
1 2020.0 R01000 北海道 5224614.0 2465088.0 2759526.0 5151366.0 2429697.0 2721669.0 555804.0 ... 77680.0 27305.0 27309.0 12255.0 9227.0 14251.0 41407.0 9394.0 26539.0 56316.0
2 2019.0 R01000 北海道 5259000.0 2480000.0 2780000.0 5223000.0 2464000.0 2759000.0 565000.0 ... 72912.0 20862.0 26332.0 9895.0 10466.0 16466.0 42277.0 8848.0 29335.0 57289.0
3 2018.0 R01000 北海道 5293000.0 2495000.0 2798000.0 5262000.0 2482000.0 2780000.0 577000.0 ... 69044.0 19089.0 27012.0 8845.0 11517.0 11437.0 39308.0 10825.0 26991.0 56984.0
4 2017.0 R01000 北海道 5325000.0 2510000.0 2815000.0 5298000.0 2499000.0 2799000.0 588000.0 ... 69640.0 24217.0 25633.0 10550.0 11222.0 12242.0 39559.0 9837.0 26797.0 57003.0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
595 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
596 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
597 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
598 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
599 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

600 rows × 112 columns

都道府県の列から、都道府県の名前を取り出してみよう。ある行以降はNaNになっているので、それを除去する。

df = pd.read_csv(url, encoding="cp932", header=1)
df = df.dropna()
df
年度 地域コード 都道府県 総人口 総人口(男) 総人口(女) 日本人人口 日本人人口(男) 日本人人口(女) 15歳未満人口 ... 食料費(二人以上の世帯) 住居費(二人以上の世帯) 光熱・水道費(二人以上の世帯) 家具・家事用品費(二人以上の世帯) 被服及び履物費(二人以上の世帯) 保健医療費(二人以上の世帯) 交通・通信費(二人以上の世帯) 教育費(二人以上の世帯) 教養娯楽費(二人以上の世帯) その他の消費支出(二人以上の世帯)
0 2021.0 R01000 北海道 5183000.0 2446000.0 2737000.0 5147000.0 2429000.0 2717000.0 544000.0 ... 71448.0 22013.0 26676.0 9912.0 8816.0 13788.0 30483.0 9913.0 23762.0 51583.0
1 2020.0 R01000 北海道 5224614.0 2465088.0 2759526.0 5151366.0 2429697.0 2721669.0 555804.0 ... 77680.0 27305.0 27309.0 12255.0 9227.0 14251.0 41407.0 9394.0 26539.0 56316.0
2 2019.0 R01000 北海道 5259000.0 2480000.0 2780000.0 5223000.0 2464000.0 2759000.0 565000.0 ... 72912.0 20862.0 26332.0 9895.0 10466.0 16466.0 42277.0 8848.0 29335.0 57289.0
3 2018.0 R01000 北海道 5293000.0 2495000.0 2798000.0 5262000.0 2482000.0 2780000.0 577000.0 ... 69044.0 19089.0 27012.0 8845.0 11517.0 11437.0 39308.0 10825.0 26991.0 56984.0
4 2017.0 R01000 北海道 5325000.0 2510000.0 2815000.0 5298000.0 2499000.0 2799000.0 588000.0 ... 69640.0 24217.0 25633.0 10550.0 11222.0 12242.0 39559.0 9837.0 26797.0 57003.0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
559 2014.0 R47000 沖縄県 1426000.0 700000.0 725000.0 1416000.0 695000.0 721000.0 249000.0 ... 56734.0 20998.0 20722.0 7509.0 6622.0 9531.0 32302.0 9016.0 18570.0 43864.0
560 2013.0 R47000 沖縄県 1419000.0 697000.0 722000.0 1410000.0 692000.0 718000.0 249000.0 ... 57278.0 23557.0 20499.0 7335.0 7398.0 9281.0 33976.0 9714.0 20199.0 50418.0
561 2012.0 R47000 沖縄県 1411000.0 693000.0 719000.0 1403000.0 688000.0 715000.0 248000.0 ... 55499.0 23731.0 19756.0 7353.0 6856.0 9948.0 27855.0 7769.0 19324.0 49890.0
562 2011.0 R47000 沖縄県 1402000.0 688000.0 714000.0 1395000.0 684000.0 711000.0 247000.0 ... 53193.0 23454.0 20645.0 6136.0 6855.0 9775.0 26806.0 7489.0 18818.0 48762.0
563 2010.0 R47000 沖縄県 1392818.0 683328.0 709490.0 1377248.0 675338.0 701910.0 246313.0 ... 54297.0 24269.0 19706.0 7306.0 7538.0 9127.0 28479.0 10577.0 20140.0 57283.0

564 rows × 112 columns

あるいは、特定の列の特定の行がNaNかどうかを調べて除外してみると

import numpy as np
df = pd.read_csv(url, encoding="cp932", header=1)
df = df.dropna(subset=['都道府県'])
df
年度 地域コード 都道府県 総人口 総人口(男) 総人口(女) 日本人人口 日本人人口(男) 日本人人口(女) 15歳未満人口 ... 食料費(二人以上の世帯) 住居費(二人以上の世帯) 光熱・水道費(二人以上の世帯) 家具・家事用品費(二人以上の世帯) 被服及び履物費(二人以上の世帯) 保健医療費(二人以上の世帯) 交通・通信費(二人以上の世帯) 教育費(二人以上の世帯) 教養娯楽費(二人以上の世帯) その他の消費支出(二人以上の世帯)
0 2021.0 R01000 北海道 5183000.0 2446000.0 2737000.0 5147000.0 2429000.0 2717000.0 544000.0 ... 71448.0 22013.0 26676.0 9912.0 8816.0 13788.0 30483.0 9913.0 23762.0 51583.0
1 2020.0 R01000 北海道 5224614.0 2465088.0 2759526.0 5151366.0 2429697.0 2721669.0 555804.0 ... 77680.0 27305.0 27309.0 12255.0 9227.0 14251.0 41407.0 9394.0 26539.0 56316.0
2 2019.0 R01000 北海道 5259000.0 2480000.0 2780000.0 5223000.0 2464000.0 2759000.0 565000.0 ... 72912.0 20862.0 26332.0 9895.0 10466.0 16466.0 42277.0 8848.0 29335.0 57289.0
3 2018.0 R01000 北海道 5293000.0 2495000.0 2798000.0 5262000.0 2482000.0 2780000.0 577000.0 ... 69044.0 19089.0 27012.0 8845.0 11517.0 11437.0 39308.0 10825.0 26991.0 56984.0
4 2017.0 R01000 北海道 5325000.0 2510000.0 2815000.0 5298000.0 2499000.0 2799000.0 588000.0 ... 69640.0 24217.0 25633.0 10550.0 11222.0 12242.0 39559.0 9837.0 26797.0 57003.0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
559 2014.0 R47000 沖縄県 1426000.0 700000.0 725000.0 1416000.0 695000.0 721000.0 249000.0 ... 56734.0 20998.0 20722.0 7509.0 6622.0 9531.0 32302.0 9016.0 18570.0 43864.0
560 2013.0 R47000 沖縄県 1419000.0 697000.0 722000.0 1410000.0 692000.0 718000.0 249000.0 ... 57278.0 23557.0 20499.0 7335.0 7398.0 9281.0 33976.0 9714.0 20199.0 50418.0
561 2012.0 R47000 沖縄県 1411000.0 693000.0 719000.0 1403000.0 688000.0 715000.0 248000.0 ... 55499.0 23731.0 19756.0 7353.0 6856.0 9948.0 27855.0 7769.0 19324.0 49890.0
562 2011.0 R47000 沖縄県 1402000.0 688000.0 714000.0 1395000.0 684000.0 711000.0 247000.0 ... 53193.0 23454.0 20645.0 6136.0 6855.0 9775.0 26806.0 7489.0 18818.0 48762.0
563 2010.0 R47000 沖縄県 1392818.0 683328.0 709490.0 1377248.0 675338.0 701910.0 246313.0 ... 54297.0 24269.0 19706.0 7306.0 7538.0 9127.0 28479.0 10577.0 20140.0 57283.0

564 rows × 112 columns

県名を取得したければ例えば

prefectures = list(df["都道府県"].unique())
print(prefectures)
['北海道', '青森県', '岩手県', '宮城県', '秋田県', '山形県', '福島県', '茨城県', '栃木県', '群馬県', '埼玉県', '千葉県', '東京都', '神奈川県', '新潟県', '富山県', '石川県', '福井県', '山梨県', '長野県', '岐阜県', '静岡県', '愛知県', '三重県', '滋賀県', '京都府', '大阪府', '兵庫県', '奈良県', '和歌山県', '鳥取県', '島根県', '岡山県', '広島県', '山口県', '徳島県', '香川県', '愛媛県', '高知県', '福岡県', '佐賀県', '長崎県', '熊本県', '大分県', '宮崎県', '鹿児島県', '沖縄県']

NaNの判定は少しトリッキーで、単純な二項演算子で判定しようとすると直感と異なる振る舞いになる。

print("nan同士を==で評価(しているつもり)", float('nan') == float('nan'))
nan同士を==で評価(しているつもり) False

さきほどのデータの例で、都道府県列からNaNでないものを取っているつもり

import numpy as np
df = pd.read_csv(url, encoding="cp932", header=1)
df[df["都道府県"] != float('nan') ]["都道府県"].unique()
array(['北海道', '青森県', '岩手県', '宮城県', '秋田県', '山形県', '福島県', '茨城県', '栃木県',
       '群馬県', '埼玉県', '千葉県', '東京都', '神奈川県', '新潟県', '富山県', '石川県', '福井県',
       '山梨県', '長野県', '岐阜県', '静岡県', '愛知県', '三重県', '滋賀県', '京都府', '大阪府',
       '兵庫県', '奈良県', '和歌山県', '鳥取県', '島根県', '岡山県', '広島県', '山口県', '徳島県',
       '香川県', '愛媛県', '高知県', '福岡県', '佐賀県', '長崎県', '熊本県', '大分県', '宮崎県',
       '鹿児島県', '沖縄県', nan], dtype=object)

Nanに対して定義された関数やメソッドを用いる必要がある。

Excelファイルの読み込み

PandasにはEXcelFileread_excelという関数が用意されていて、多数のシートを含むようなエクセルファイルを開くことも出来る。

今まではGoogle Driveにいれたファイルを読み出していたが、
Webから直接xlsxファイルを読み込んでみよう。

url = "https://www.mext.go.jp/content/20201225-mxt_kagsei-mext_01110_012.xlsx"
input_file = pd.ExcelFile(url)

ブック内のシートの一覧は以下のように取得できる。

sheet_names = input_file.sheet_names
print("pandas: シート名",sheet_names)
pandas: シート名 ['表全体', '1穀類', '2いも及びでん粉類', '3砂糖及び甘味類', '4豆類', '5種実類', '6野菜類', '7果実類', '8きのこ類', '9藻類', '10魚介類', '11肉類', '12鶏卵', '13乳類', '14油脂類', '15菓子類', '16し好飲料', '17調味料及び香辛料', '18調理済み流通食品類']

シートを指定するのは、インデックスかシート名の文字列で行う。

“1 穀類”を使うことにして、
pandasにあるread_excel関数を使ってみよう。
read_excel関数の最初の引数にはパスの他に、urlも取れる。

df = pd.read_excel(url,sheet_name="1穀類")
df
Unnamed: 0 Unnamed: 1 Unnamed: 2 Unnamed: 3 Unnamed: 4 Unnamed: 5 Unnamed: 6 Unnamed: 7 Unnamed: 8 Unnamed: 9 ... Unnamed: 52 Unnamed: 53 Unnamed: 54 Unnamed: 55 Unnamed: 56 Unnamed: 57 Unnamed: 58 Unnamed: 59 Unnamed: 60 更新日:2021年12月28日
0 NaN 食 品 番 号 索 引 番 号 可  食  部   100  g  当  た  り NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN 備  考
1 NaN NaN NaN 食 品 名 廃 棄 率 エネルギー NaN 水 分 たんぱく質 NaN ... NaN NaN NaN NaN NaN NaN NaN アルコール 食塩相当量 NaN
2 NaN NaN NaN NaN NaN NaN NaN NaN アミノ酸組成による\nたんぱく質 たんぱく質 ... ナイアシン当量 ビ\nタ\nミ\nン\nB6 ビ\nタ\nミ\nン\nB12 葉 酸 パントテン酸 ビ オ チ ン ビタミンC NaN NaN NaN
3 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
4 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
211 1.0 01139 201 ひえ 精白粒 0 1534 361 12.9 8.4 9.4 ... 2.3 0.17 (0) 14 1.50 3.6 0 - 0 歩留り: 55~60 %
212 1.0 01140 202 もろこし 玄穀 0 1454 344 12.0 (9.0) 10.3 ... (8.0) 0.31 (0) 54 1.42 15.0 (0) - 0 別名: こうりゃん、ソルガム、たかきび、マイロ
213 1.0 01141 203 もろこし 精白粒 0 1473 348 12.5 (8.0) 9.5 ... (5.0) 0.24 (0) 29 0.66 - (0) - 0 別名: こうりゃん、ソルガム、たかきび、マイロ\n歩留り: 70~80 %
214 1.0 01142 204 ライむぎ 全粒粉 0 1342 317 12.5 10.8 12.7 ... 4.2 0.22 (0) 65 0.87 9.5 0 - 0 別名:黒麦(くろむぎ)
215 1.0 01143 205 ライむぎ ライ麦粉 0 1368 324 13.5 7.8 8.5 ... 2.6 0.10 (0) 34 0.63 - (0) - 0 別名:黒麦(くろむぎ)\n歩留り: 65~75 %

216 rows × 62 columns

同じものが得られている。

Excelファイルの読み込みに関する補足

pandas内部ではExcelFileというクラスがExcelファイルを扱うために用意されている。

Excelファイルが単一のシートしかない場合や、上でやったようにExcelFile化してシート名を既に知っている場合は、read_excel関数で直接読み込むことができ、DataFrameとして取得できる。

ファイルによっては、読み込む際にエラーが出ることがある。

その場合、openpyxlというライブラリをインストールすることで解決することがある。 以下のようにしてインストールし、read_excelのオプションとしてengine="openpyxl"を指定するとよい。

!pip install openpyxl
df = pd.read_excel('filepath.xlsx',engine="openpyxl")

Pythonには伝統的にExcelファイルを扱うためのライブラリが複数存在しており、pandasの内部でも用いられている。 中でも、ファイルを読み込む際に良く用いられてきたのがxlrdである。 pandasのバージョン1.1まではExcelファイルを扱う際、内部的にxlrdを使用していたが、v1.2からは.xlsx形式はopenpyxl.xlsxlrdを使用するようになった。 https://pandas.pydata.org/pandas-docs/stable/whatsnew/v1.2.0.html

したがって、使用している環境でopenpyxlxlrdなどがなければインストールしたり、ファイルを読み込む際に明示的にengineを指定してやる必要がある。

データの整形

次に、今取得したデータフレームのままでは少々扱い辛いので”整形”を考える。
というのも前から4行ほど表示してみると…

df[0:4] 
Unnamed: 0 Unnamed: 1 Unnamed: 2 Unnamed: 3 Unnamed: 4 Unnamed: 5 Unnamed: 6 Unnamed: 7 Unnamed: 8 Unnamed: 9 ... Unnamed: 52 Unnamed: 53 Unnamed: 54 Unnamed: 55 Unnamed: 56 Unnamed: 57 Unnamed: 58 Unnamed: 59 Unnamed: 60 更新日:2021年12月28日
0 NaN 食 品 番 号 索 引 番 号 可  食  部   100  g  当  た  り NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN 備  考
1 NaN NaN NaN 食 品 名 廃 棄 率 エネルギー NaN 水 分 たんぱく質 NaN ... NaN NaN NaN NaN NaN NaN NaN アルコール 食塩相当量 NaN
2 NaN NaN NaN NaN NaN NaN NaN NaN アミノ酸組成による\nたんぱく質 たんぱく質 ... ナイアシン当量 ビ\nタ\nミ\nン\nB6 ビ\nタ\nミ\nン\nB12 葉 酸 パントテン酸 ビ オ チ ン ビタミンC NaN NaN NaN
3 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

4 rows × 62 columns

最初の4行ほどに栄養素等の情報が入っているのだが、
セルが結合されたりしているため、所々にNaNが入っていたりして見辛い。

(碁盤目の構造を破壊してしまうため「セルの結合」は機械的な処理と
やや相性が悪く、プログラミングを用いたデータ分析では嫌われる)

各省庁の公開データのフォーマットの統一化は今後に期待することにして…
まず以下の項目に該当する列だけを抽出する事を考える。

targets = ["食品名", "エネルギー","たんぱく質", "脂質", "炭水化物"]

該当するデータがどの行・列に格納されているかをコードで指定するのは、
前述のファイル構造の事情からやや面倒くさい。

以下では、その場しのぎ的ではあるが、
興味のある量が何番目かを指定してまとめてみることにしよう。

そのために、1-2行目の要素を表示してみよう。

#1-2行目(エクセルだと2行目)の要素から
    #半角空白, 全角空白(\u3000)や改行コード\nを取り除いたリストを作って表示してみる

for idx in range(1,3):
    tmp = df.iloc[idx].values
    tlist = list(map( lambda s: str(s).replace("\u3000","").replace("\n","").replace(" ",""),tmp))
    print(tlist)
['nan', 'nan', 'nan', '食品名', '廃棄率', 'エネルギー', 'nan', '水分', 'たんぱく質', 'nan', '脂質', 'nan', 'nan', '炭水化物', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', '有機酸', '灰分', '無機質', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', '無機質', 'nan', 'nan', 'nan', 'ビタミン', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'アルコール', '食塩相当量', 'nan']
['nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'nan', 'アミノ酸組成によるたんぱく質', 'たんぱく質', '脂肪酸のトリアシルグリセロール当量', 'コレステロール', '脂質', '利用可能炭水化物', 'nan', 'nan', 'nan', 'nan', '食物繊維総量', '糖アルコール', '炭水化物', 'nan', 'nan', 'ナトリウム', 'カリウム', 'カルシウム', 'マグネシウム', 'リン', '鉄', '亜鉛', '銅', 'マンガン', 'nan', 'ヨウ素', 'セレン', 'クロム', 'モリブデン', 'ビタミンA', 'nan', 'nan', 'nan', 'nan', 'nan', 'ビタミンD', 'ビタミンE', 'nan', 'nan', 'nan', 'ビタミンK', 'ビタミンB1', 'ビタミンB2', 'ナイアシン', 'ナイアシン当量', 'ビタミンB6', 'ビタミンB12', '葉酸', 'パントテン酸', 'ビオチン', 'ビタミンC', 'nan', 'nan', 'nan']

セルの結合により、興味のあるデータがどの列に記述されているかは注意が必要。

実際、[エネルギー]という文字列は1行目の6列目(それぞれインデックスでいうと0,5)で取得できるが、
kJ単位になっていて、kcal単位でほしければ、7列目に格納された値が必要になる。

また、エクセルファイルを見るとわかるように、たんぱく質・脂質・炭水化物はさらに細分化されており、
O列R列など、細かい列の分割が挿入されている. ~~これは大変困る~~

単純にたんぱく質・脂質・炭水化物と表記されている列のインデックスはそれぞれ9,12,20となる。
食品名が格納されている列(3)、エネルギー[kJ単位] (6)と合わせて確認してみよう。

targets = [3,6,9,12,20]
df.iloc[:,targets]
Unnamed: 3 Unnamed: 6 Unnamed: 9 Unnamed: 12 Unnamed: 20
0 可  食  部   100  g  当  た  り NaN NaN NaN NaN
1 食 品 名 NaN NaN NaN NaN
2 NaN NaN たんぱく質 脂質 炭水化物
3 NaN NaN NaN NaN NaN
4 NaN NaN NaN NaN NaN
... ... ... ... ... ...
211 ひえ 精白粒 361 9.4 3.3 73.2
212 もろこし 玄穀 344 10.3 4.7 71.1
213 もろこし 精白粒 348 9.5 2.6 74.1
214 ライむぎ 全粒粉 317 12.7 2.7 70.7
215 ライむぎ ライ麦粉 324 8.5 1.6 75.8

216 rows × 5 columns

もう少し整形したいので、新しいデータフレームの列を書き換える。

食品名等が記載されているのは10行目以降なので、それを使いcolumnsを指定する。

さらに、食品名に含まれる余分な文字コードも削除しておこう。

ndf = df.iloc[:,targets] 
ndf = ndf.iloc[10:,:]
ndf.columns=["食品名","エネルギー(kcal)","たんぱく質(g)","脂質(g)","炭水化物(g)"]
ndf["食品名"] = ndf["食品名"].str.replace("\u3000"," ") # 食品名の中にある余分な全角空白(\u3000)を半角スペースに置き換える
ndf
食品名 エネルギー(kcal) たんぱく質(g) 脂質(g) 炭水化物(g)
10 成分識別子 ENERC_KCAL PROT- FAT- CHOCDF-
11 アマランサス 玄穀 343 12.7 6.0 64.9
12 あわ 精白粒 346 11.2 4.4 69.7
13 あわ あわもち 210 5.1 1.3 45.3
14 えんばく オートミール 350 13.7 5.7 69.1
... ... ... ... ... ...
211 ひえ 精白粒 361 9.4 3.3 73.2
212 もろこし 玄穀 344 10.3 4.7 71.1
213 もろこし 精白粒 348 9.5 2.6 74.1
214 ライむぎ 全粒粉 317 12.7 2.7 70.7
215 ライむぎ ライ麦粉 324 8.5 1.6 75.8

206 rows × 5 columns

次に、食品名の一覧を取得した後、興味のあるもの(日常的に馴染みのあるもの)だけを
ピックアップしてみよう。

print(list(ndf["食品名"]))
['成分識別子', 'アマランサス 玄穀', 'あわ 精白粒', 'あわ あわもち', 'えんばく オートミール', 'おおむぎ 七分つき押麦', 'おおむぎ 押麦 乾', 'おおむぎ 押麦 めし', 'おおむぎ 米粒麦', 'おおむぎ 大麦めん 乾', 'おおむぎ 大麦めん ゆで', 'おおむぎ 麦こがし', 'キヌア 玄穀', 'きび 精白粒', 'こむぎ [玄穀] 国産 普通', 'こむぎ [玄穀] 輸入 軟質', 'こむぎ [玄穀] 輸入 硬質', 'こむぎ [小麦粉] 薄力粉 1等', 'こむぎ [小麦粉] 薄力粉 2等', 'こむぎ [小麦粉] 中力粉 1等', 'こむぎ [小麦粉] 中力粉 2等', 'こむぎ [小麦粉] 強力粉 1等', 'こむぎ [小麦粉] 強力粉 2等', 'こむぎ [小麦粉] 強力粉 全粒粉', 'こむぎ [小麦粉] プレミックス粉 お好み焼き用', 'こむぎ [小麦粉] プレミックス粉 ホットケーキ用', 'こむぎ [小麦粉] プレミックス粉 から揚げ用', 'こむぎ [小麦粉] プレミックス粉 天ぷら用', 'こむぎ [小麦粉] プレミックス粉 天ぷら用 バッター', 'こむぎ [小麦粉] プレミックス粉 天ぷら用 バッター 揚げ', 'こむぎ [パン類] 角形食パン 食パン', 'こむぎ [パン類] 角形食パン 焼き', 'こむぎ [パン類] 角形食パン 耳を除いたもの', 'こむぎ [パン類] 角形食パン 耳', 'こむぎ [パン類] 食パン リーンタイプ', 'こむぎ [パン類] 食パン リッチタイプ', 'こむぎ [パン類] 山形食パン 食パン', 'こむぎ [パン類] コッペパン', 'こむぎ [パン類] 乾パン', 'こむぎ [パン類] フランスパン', 'こむぎ [パン類] ライ麦パン', 'こむぎ [パン類] 全粒粉パン', 'こむぎ [パン類] ぶどうパン', 'こむぎ [パン類] ロールパン', 'こむぎ [パン類] クロワッサン レギュラータイプ', 'こむぎ [パン類] クロワッサン リッチタイプ', 'こむぎ [パン類] くるみパン', 'こむぎ [パン類] イングリッシュマフィン', 'こむぎ [パン類] ナン', 'こむぎ [パン類] ベーグル', 'こむぎ [うどん・そうめん類] うどん 生', 'こむぎ [うどん・そうめん類] うどん ゆで', 'こむぎ [うどん・そうめん類] うどん 半生うどん', 'こむぎ [うどん・そうめん類] 干しうどん 乾', 'こむぎ [うどん・そうめん類] 干しうどん ゆで', 'こむぎ [うどん・そうめん類] そうめん・ひやむぎ 乾', 'こむぎ [うどん・そうめん類] そうめん・ひやむぎ ゆで', 'こむぎ [うどん・そうめん類] 手延そうめん・手延ひやむぎ 乾', 'こむぎ [うどん・そうめん類] 手延そうめん・手延ひやむぎ ゆで', 'こむぎ [中華めん類] 中華めん 生', 'こむぎ [中華めん類] 中華めん ゆで', 'こむぎ [中華めん類] 半生中華めん ', 'こむぎ [中華めん類] 蒸し中華めん 蒸し中華めん', 'こむぎ [中華めん類] 蒸し中華めん  ソテー', 'こむぎ [中華めん類] 干し中華めん 乾', 'こむぎ [中華めん類] 干し中華めん ゆで', 'こむぎ [中華めん類] 沖縄そば 生', 'こむぎ [中華めん類] 沖縄そば ゆで', 'こむぎ [中華めん類] 干し沖縄そば 乾', 'こむぎ [中華めん類] 干し沖縄そば ゆで', 'こむぎ [即席めん類] 即席中華めん 油揚げ味付け', 'こむぎ [即席めん類] 即席中華めん 油揚げ 乾 (添付調味料等を含むもの)', 'こむぎ [即席めん類] 即席中華めん 油揚げ 調理後全体 (添付調味料等を含むもの)', 'こむぎ [即席めん類] 即席中華めん 油揚げ ゆで (添付調味料等を含まないもの)', 'こむぎ [即席めん類] 即席中華めん 油揚げ 乾 (添付調味料等を含まないもの)', 'こむぎ [即席めん類] 即席中華めん 非油揚げ 乾 (添付調味料等を含むもの)', 'こむぎ [即席めん類] 即席中華めん 非油揚げ 調理後全体 (添付調味料等を含むもの)', 'こむぎ [即席めん類] 即席中華めん 非油揚げ ゆで (添付調味料等を含まないもの)', 'こむぎ [即席めん類] 即席中華めん 非油揚げ 乾 (添付調味料等を含まないもの)', 'こむぎ [即席めん類] 中華スタイル即席カップめん 油揚げ 塩味 乾 (添付調味料等を含むもの)', 'こむぎ [即席めん類] 中華スタイル即席カップめん 油揚げ 塩味 調理後全体 (添付調味料等を含むもの)', 'こむぎ [即席めん類] 中華スタイル即席カップめん 油揚げ 塩味 調理後のめん (スープを残したもの)', 'こむぎ [即席めん類] 中華スタイル即席カップめん 油揚げ しょうゆ味 乾 (添付調味料等を含むもの)', 'こむぎ [即席めん類] 中華スタイル即席カップめん 油揚げ しょうゆ味 調理後全体 (添付調味料等を含むもの)', 'こむぎ [即席めん類] 中華スタイル即席カップめん 油揚げ しょうゆ味 調理後のめん (スープを残したもの)', 'こむぎ [即席めん類] 中華スタイル即席カップめん 油揚げ 焼きそば 乾 (添付調味料等を含むもの)', 'こむぎ [即席めん類] 中華スタイル即席カップめん 油揚げ 焼きそば 調理後全体 (添付調味料等を含むもの)', 'こむぎ [即席めん類] 中華スタイル即席カップめん 非油揚げ 乾 (添付調味料等を含むもの)', 'こむぎ [即席めん類] 中華スタイル即席カップめん 非油揚げ 調理後全体 (添付調味料等を含むもの)', 'こむぎ [即席めん類] 中華スタイル即席カップめん 非油揚げ 調理後のめん (スープを残したもの)', 'こむぎ [即席めん類] 和風スタイル即席カップめん 油揚げ 乾 (添付調味料等を含むもの)', 'こむぎ [即席めん類] 和風スタイル即席カップめん 油揚げ 調理後全体 (添付調味料等を含むもの)', 'こむぎ [即席めん類] 和風スタイル即席カップめん 油揚げ 調理後のめん (スープを残したもの)', 'こむぎ [マカロニ・スパゲッティ類] マカロニ・スパゲッティ 乾', 'こむぎ [マカロニ・スパゲッティ類] マカロニ・スパゲッティ ゆで', 'こむぎ [マカロニ・スパゲッティ類] マカロニ・スパゲッティ ソテー', 'こむぎ [マカロニ・スパゲッティ類] 生パスタ 生', 'こむぎ [ふ類] 生ふ', 'こむぎ [ふ類] 焼きふ 釜焼きふ', 'こむぎ [ふ類] 焼きふ 板ふ', 'こむぎ [ふ類] 焼きふ 車ふ', 'こむぎ [ふ類] 油ふ', 'こむぎ [その他] 小麦はいが', 'こむぎ [その他] 小麦たんぱく 粉末状', 'こむぎ [その他] 小麦たんぱく 粒状', 'こむぎ [その他] 小麦たんぱく ペースト状', 'こむぎ [その他] かやきせんべい', 'こむぎ [その他] ぎょうざの皮 生', 'こむぎ [その他] しゅうまいの皮 生', 'こむぎ [その他] 春巻きの皮 生', 'こむぎ [その他] 春巻きの皮 揚げ', 'こむぎ [その他] ピザ生地', 'こむぎ [その他] ちくわぶ', 'こむぎ [その他] パン粉 生', 'こむぎ [その他] パン粉 半生', 'こむぎ [その他] パン粉 乾燥', 'こむぎ [その他] 冷めん 生', 'こめ [水稲穀粒] 玄米', 'こめ [水稲穀粒] 半つき米', 'こめ [水稲穀粒] 七分つき米', 'こめ [水稲穀粒] 精白米 うるち米', 'こめ [水稲穀粒] 精白米 もち米', 'こめ [水稲穀粒] 精白米 インディカ米', 'こめ [水稲穀粒] はいが精米', 'こめ [水稲穀粒] 発芽玄米', 'こめ [水稲穀粒] 赤米', 'こめ [水稲穀粒] 黒米', 'こめ [水稲めし] 玄米', 'こめ [水稲めし] 半つき米', 'こめ [水稲めし] 七分つき米', 'こめ [水稲めし] 精白米 インディカ米', 'こめ [水稲めし] 精白米 うるち米', 'こめ [水稲めし] 精白米 もち米', 'こめ [水稲めし] はいが精米', 'こめ [水稲めし] 発芽玄米', 'こめ [水稲めし] 赤米', 'こめ [水稲めし] 黒米', 'こめ [水稲軟めし] 精白米', 'こめ [水稲全かゆ] 玄米', 'こめ [水稲全かゆ] 半つき米', 'こめ [水稲全かゆ] 七分つき米', 'こめ [水稲全かゆ] 精白米', 'こめ [水稲五分かゆ] 玄米', 'こめ [水稲五分かゆ] 半つき米', 'こめ [水稲五分かゆ] 七分つき米', 'こめ [水稲五分かゆ] 精白米', 'こめ [水稲おもゆ] 玄米', 'こめ [水稲おもゆ] 半つき米', 'こめ [水稲おもゆ] 七分つき米', 'こめ [水稲おもゆ] 精白米', 'こめ [陸稲穀粒] 玄米', 'こめ [陸稲穀粒] 半つき米', 'こめ [陸稲穀粒] 七分つき米', 'こめ [陸稲穀粒] 精白米', 'こめ [陸稲めし] 玄米', 'こめ [陸稲めし] 半つき米', 'こめ [陸稲めし] 七分つき米', 'こめ [陸稲めし] 精白米', 'こめ [うるち米製品] アルファ化米 一般用', 'こめ [うるち米製品] アルファ化米 学校給食用強化品', 'こめ [うるち米製品] おにぎり', 'こめ [うるち米製品] 焼きおにぎり', 'こめ [うるち米製品] きりたんぽ', 'こめ [うるち米製品] 上新粉', 'こめ [うるち米製品] 玄米粉', 'こめ [うるち米製品] 米粉', 'こめ [うるち米製品] 米粉パン 食パン', 'こめ [うるち米製品] 米粉パン ロールパン', 'こめ [うるち米製品] 米粉パン 小麦グルテン不使用のもの', 'こめ [うるち米製品] 米粉めん', 'こめ [うるち米製品] ビーフン', 'こめ [うるち米製品] ライスペーパー', 'こめ [うるち米製品] 米こうじ', 'こめ [もち米製品] もち', 'こめ [もち米製品] 赤飯', 'こめ [もち米製品] あくまき', 'こめ [もち米製品] 白玉粉', 'こめ [もち米製品] 道明寺粉', 'こめ [その他] 米ぬか', 'そば そば粉 全層粉', 'そば そば粉 内層粉', 'そば そば粉 中層粉', 'そば そば粉 表層粉', 'そば そば米', 'そば そば 生', 'そば そば ゆで', 'そば そば 半生そば', 'そば 干しそば 乾', 'そば 干しそば ゆで', 'とうもろこし 玄穀 黄色種', 'とうもろこし 玄穀 白色種', 'とうもろこし コーンミール 黄色種', 'とうもろこし コーンミール 白色種', 'とうもろこし コーングリッツ 黄色種', 'とうもろこし コーングリッツ 白色種', 'とうもろこし コーンフラワー 黄色種', 'とうもろこし コーンフラワー 白色種', 'とうもろこし ジャイアントコーン フライ 味付け', 'とうもろこし ポップコーン', 'とうもろこし コーンフレーク', 'はとむぎ 精白粒', 'ひえ 精白粒', 'もろこし 玄穀', 'もろこし 精白粒', 'ライむぎ 全粒粉', 'ライむぎ ライ麦粉']

この中から…

  • こむぎ[パン類]食パンリッチタイプ

  • こむぎ[パン類]フランスパン

  • こめ[水稲軟めし]精白米

  • そばそばゆで

  • こむぎ[うどん・そうめん類]うどんゆで

のみに興味があれば

tshokuhin = ["こむぎ [パン類] 食パン リッチタイプ","こむぎ [パン類] フランスパン","こめ [水稲軟めし] 精白米", "そば そば ゆで", "こむぎ [うどん・そうめん類] うどん ゆで"]
ndf[ ndf["食品名"].isin(tshokuhin)]
食品名 エネルギー(kcal) たんぱく質(g) 脂質(g) 炭水化物(g)
45 こむぎ [パン類] 食パン リッチタイプ 256 (7.8) (6.0) (45.6)
49 こむぎ [パン類] フランスパン 289 9.4 1.3 57.5
61 こむぎ [うどん・そうめん類] うどん ゆで 95 2.6 0.4 21.6
147 こめ [水稲軟めし] 精白米 113 (1.8) (0.3) (26.4)
195 そば そば ゆで 130 4.8 1.0 26.0

などとする。

‘6野菜類’でも同様に…

df6 = pd.read_excel(url,sheet_name="6野菜類")
df6.iloc[:,[3,6,9,12,20]]
ndf6 = df6.iloc[:,[3,6,9,12,20]] 
ndf6 = ndf6.iloc[10:,:]
ndf6.columns=["食品名","エネルギー(kcal)","たんぱく質(g)","脂質(g)","炭水化物(g)"]
ndf6["食品名"] = ndf6["食品名"].str.replace("\u3000"," ") 
ndf6
食品名 エネルギー(kcal) たんぱく質(g) 脂質(g) 炭水化物(g)
10 成分識別子 ENERC_KCAL PROT- FAT- CHOCDF-
11 アーティチョーク 花らい 生 39 2.3 0.2 11.3
12 アーティチョーク 花らい ゆで 35 2.1 0.1 10.8
13 あさつき 葉 生 34 4.2 0.3 5.6
14 あさつき 葉 ゆで 41 4.2 0.3 7.3
... ... ... ... ... ...
407 (その他) ミックスベジタブル 冷凍 67 3.0 0.7 15.1
408 (その他) ミックスベジタブル 冷凍 ゆで 65 3.1 0.8 14.6
409 (その他) ミックスベジタブル 冷凍 油いため 108 3.3 4.9 15.7
410 (その他) 野菜ミックスジュース 通常タイプ 21 0.8 0.1 4.7
411 (その他) 野菜ミックスジュース 濃縮タイプ 36 1.0 0.3 7.8

402 rows × 5 columns

特定のキーワードを含むものを全て取得して、
食品名を細かく指定したり、対応する行番号のインデックスを取得できたりする

kyabetu = ndf6[ndf6["食品名"].str.contains('キャベツ')]
kyabetu
食品名 エネルギー(kcal) たんぱく質(g) 脂質(g) 炭水化物(g)
81 (キャベツ類) キャベツ 結球葉 生 21 1.3 0.2 5.2
82 (キャベツ類) キャベツ 結球葉 ゆで 19 0.9 0.2 4.6
83 (キャベツ類) キャベツ 結球葉 油いため 78 1.6 6.0 5.9
84 (キャベツ類) グリーンボール 結球葉 生 20 1.4 0.1 4.3
85 (キャベツ類) レッドキャベツ 結球葉 生 30 2.0 0.1 6.7
358 めキャベツ 結球葉 生 52 5.7 0.1 9.9
359 めキャベツ 結球葉 ゆで 51 5.3 0.1 9.8
tomato = ndf6[ndf6["食品名"].str.contains('トマト')]
tomato
食品名 エネルギー(kcal) たんぱく質(g) 脂質(g) 炭水化物(g)
221 (トマト類) 赤色トマト 果実 生 20 0.7 0.1 4.7
222 (トマト類) 赤色ミニトマト 果実 生 30 1.1 0.1 7.2
223 (トマト類) 黄色トマト 果実 生 18 1.1 0.4 3.2
224 (トマト類) ドライトマト 291 14.2 2.1 67.3
225 (トマト類) 加工品 ホール 食塩無添加 21 0.9 0.2 4.4
226 (トマト類) 加工品 トマトジュース 食塩添加 15 0.7 0.1 4.0
227 (トマト類) 加工品 トマトジュース 食塩無添加 18 0.7 0.1 4.0
228 (トマト類) 加工品 ミックスジュース 食塩添加 18 0.6 0 4.3
229 (トマト類) 加工品 ミックスジュース 食塩無添加 18 0.6 0 4.3

DataFrame同士を結合してまとめるなどして扱いやすいデータに整形していく.

縦方向の結合はpandasのconcat(concatenateの略)を使う。

tdf = pd.concat([kyabetu, tomato])
tdf
食品名 エネルギー(kcal) たんぱく質(g) 脂質(g) 炭水化物(g)
81 (キャベツ類) キャベツ 結球葉 生 21 1.3 0.2 5.2
82 (キャベツ類) キャベツ 結球葉 ゆで 19 0.9 0.2 4.6
83 (キャベツ類) キャベツ 結球葉 油いため 78 1.6 6.0 5.9
84 (キャベツ類) グリーンボール 結球葉 生 20 1.4 0.1 4.3
85 (キャベツ類) レッドキャベツ 結球葉 生 30 2.0 0.1 6.7
358 めキャベツ 結球葉 生 52 5.7 0.1 9.9
359 めキャベツ 結球葉 ゆで 51 5.3 0.1 9.8
221 (トマト類) 赤色トマト 果実 生 20 0.7 0.1 4.7
222 (トマト類) 赤色ミニトマト 果実 生 30 1.1 0.1 7.2
223 (トマト類) 黄色トマト 果実 生 18 1.1 0.4 3.2
224 (トマト類) ドライトマト 291 14.2 2.1 67.3
225 (トマト類) 加工品 ホール 食塩無添加 21 0.9 0.2 4.4
226 (トマト類) 加工品 トマトジュース 食塩添加 15 0.7 0.1 4.0
227 (トマト類) 加工品 トマトジュース 食塩無添加 18 0.7 0.1 4.0
228 (トマト類) 加工品 ミックスジュース 食塩添加 18 0.6 0 4.3
229 (トマト類) 加工品 ミックスジュース 食塩無添加 18 0.6 0 4.3

DataFrameのcsv/Excelファイルへの書き出し

DataFrameオブジェクトは、pandas内の関数・メソッドを用いれば、簡単にcsvやExcelファイルとして書き出すことができる。

実行履歴に残っている適当なDataFrameを、Google Driveにファイルとして書き出してみよう。

from google.colab import drive
drive.mount('/content/drive')

csvとして書き出す場合

適当にパスを指定して、DataFrameオブジェクトにto_csv関数を作用させる。

df.to_csv("/content/drive/MyDrive/pd_write_test.csv")

Excelファイルとして書き出す場合

この場合も同様で、to_excel関数を用いればよい。

df.to_excel("/content/drive/MyDrive/pd_write_test.xlsx")

上記の関数内で書き出しに使う文字コードを指定することもできる。
例: encoding="utf-8_sig", encoding="shift_jis"