{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "c2590179",
   "metadata": {},
   "source": [
    "# pandasでデータ加工（45分）\n",
    "\n",
    "この章では、pandasを使って表形式のデータを読み込み、加工し、集計する流れを体験します。\n",
    "\n",
    "```{note}\n",
    "入力が遅れた場合などに、{nb-download}`この章のNotebook <5_pandas.ipynb>`をダウンロードできます。ダウンロードしたファイルを作業フォルダに置き、JupyterLabのファイルブラウザでダブルクリックして開いてください。\n",
    "ダウンロードしたNotebookには、この章の説明の文章も入っています。図などの一部の書き方は、JupyterLabでは記号のまま表示されます。\n",
    "\n",
    "自分で作った`5_pandas.ipynb`と同じ名前のため、上書きしないように注意してください。\n",
    "```\n",
    "\n",
    "## pandasとは\n",
    "\n",
    "**pandas**はオープンソースのデータ分析と加工のためのライブラリです。\n",
    "表形式のデータを読み込み、加工、集計といった作業ができます。\n",
    "Excelのような行と列を持つ表のデータを、Pythonのコードで扱えます。\n",
    "CSVファイルなどからデータを読み込み、必要な行や列を取り出したり、抜けている値を補ったり、複数の表をつなげたり、グループごとに集計したりできます。\n",
    "\n",
    "* pandas公式サイト：<https://pandas.pydata.org/>\n",
    "\n",
    "第4章の{ref}`jupyter-start`の手順で、作業フォルダでJupyterLabを起動してください。\n",
    "新しいNotebookを作成し、名前を`5_pandas.ipynb`に変更します。\n",
    "\n",
    "最初のセルでpandasをインポートします。\n",
    "pandasは`pd`という別名でインポートするのが慣例です。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "b2a8dd38",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "57eaf28d",
   "metadata": {},
   "source": [
    "## SeriesとDataFrame\n",
    "\n",
    "pandasでは、主にSeriesとDataFrameの2種類の形でデータを扱います。\n",
    "\n",
    "**Series**は、1次元のデータです。\n",
    "値の並びに、**インデックス**というラベルが付いています。\n",
    "次のコードでは、商品名をインデックス、単価を値としたSeriesを作ります。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "4bb376a0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "コーヒー    400\n",
       "紅茶      450\n",
       "ケーキ     500\n",
       "dtype: int64"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "prices = pd.Series([400, 450, 500], index=[\"コーヒー\", \"紅茶\", \"ケーキ\"])\n",
    "prices"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4f145ce0",
   "metadata": {},
   "source": [
    "左側の商品名がインデックス、右側の数値が値です。\n",
    "最後の行の`dtype`は値のデータ型で、`int64`は整数を表します。\n",
    "インデックスは`index`で確認できます。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "504aba02",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Index(['コーヒー', '紅茶', 'ケーキ'], dtype='str')"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "prices.index"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fd6aad85",
   "metadata": {},
   "source": [
    "**DataFrame**は、行と列を持つ表です。\n",
    "列名と列の値を辞書で渡して作ります。\n",
    "DataFrameの各列はSeriesです。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "b4f1593a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>item</th>\n",
       "      <th>price</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>コーヒー</td>\n",
       "      <td>400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>紅茶</td>\n",
       "      <td>450</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>ケーキ</td>\n",
       "      <td>500</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   item  price\n",
       "0  コーヒー    400\n",
       "1    紅茶    450\n",
       "2   ケーキ    500"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "items = pd.DataFrame({\"item\": [\"コーヒー\", \"紅茶\", \"ケーキ\"], \"price\": [400, 450, 500]})\n",
    "items"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a270c6d4",
   "metadata": {},
   "source": [
    "DataFrameの行にもインデックスが付きます。\n",
    "インデックスを指定せずに作ると、0から始まる番号（`RangeIndex`）になります。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "6cb91371",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "RangeIndex(start=0, stop=3, step=1)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "items.index"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1c5722b7",
   "metadata": {},
   "source": [
    "列名は`columns`で確認できます。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "8f2635ba",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Index(['item', 'price'], dtype='str')"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "items.columns"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "de910ad6",
   "metadata": {},
   "source": [
    "## CSVファイルの書き出しと読み込み\n",
    "\n",
    "**CSVファイル**は、表形式のデータを保存するテキストファイルです。\n",
    "表の1行をファイルの1行に書き、値をカンマ（`,`）で区切って並べます。\n",
    "多くのツールで読み書きできるため、表形式データの保存によく使われるフォーマットです。\n",
    "\n",
    "DataFrameは`to_csv()`メソッドでCSVファイルに書き出せます。\n",
    "`index=False`を指定すると、インデックスを書き出しません。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "6b15ff85",
   "metadata": {},
   "outputs": [],
   "source": [
    "items.to_csv(\"items.csv\", index=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "be592e3d",
   "metadata": {},
   "source": [
    "上のコードを実行すると作業フォルダに`items.csv`ができます。\n",
    "ファイルの中身は次のようなテキストです。\n",
    "1行目が列名で、2行目以降が表の各行です。\n",
    "\n",
    "```text\n",
    "item,price\n",
    "コーヒー,400\n",
    "紅茶,450\n",
    "ケーキ,500\n",
    "```\n",
    "\n",
    "JupyterLabのファイルブラウザで`items.csv`をダブルクリックすると、表形式で開きます。\n",
    "左端の番号は表示のための行番号で、DataFrameのインデックスではありません。\n",
    "\n",
    "```{figure} images/5_items_csv.png\n",
    ":alt: items.csvを開いたJupyterLabの画面\n",
    "\n",
    "`items.csv`を開いたJupyterLabの画面\n",
    "```\n",
    "\n",
    "CSVファイルは`pd.read_csv()`関数で読み込みます。\n",
    "読み込んだ表は、書き出す前の`items`と同じになります。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "f6a9e0b2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>item</th>\n",
       "      <th>price</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>コーヒー</td>\n",
       "      <td>400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>紅茶</td>\n",
       "      <td>450</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>ケーキ</td>\n",
       "      <td>500</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   item  price\n",
       "0  コーヒー    400\n",
       "1    紅茶    450\n",
       "2   ケーキ    500"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "items_csv = pd.read_csv(\"items.csv\")\n",
    "items_csv"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f1dfbf76",
   "metadata": {},
   "source": [
    "## 売上データを読み込む\n",
    "\n",
    "この節からは、架空の店舗の売上データを使います。\n",
    "2026年4月1日から30日までについて、店舗ごと、商品ごとの毎日の販売数を記録したデータです（実在の店舗とは関係ありません）。\n",
    "データには次の列があります。\n",
    "\n",
    "```{table} 売上データの列\n",
    "| 列名 | 内容 |\n",
    "|---|---|\n",
    "| `date` | 日付 |\n",
    "| `store` | 店舗 |\n",
    "| `item` | 商品 |\n",
    "| `quantity` | 販売数 |\n",
    "| `price` | 単価 |\n",
    "```\n",
    "\n",
    "次の2つのファイルをダウンロードし、作業フォルダの直下（`5_pandas.ipynb`と同じ場所）に置いてください。\n",
    "\n",
    "* {download}`sales.csv`：売上データ（この節で使います）\n",
    "* {download}`sales_next_month.csv`：翌月の売上（「データを連結する」で使います）\n",
    "\n",
    "```{note}\n",
    "`sales.csv`の中身は、JupyterLabで開いて確認してください。\n",
    "Excelで開くと文字化けすることがあります。\n",
    "```\n",
    "\n",
    "`pd.read_csv()`関数で売上データを読み込みます。\n",
    "`parse_dates`に列名を指定すると、その列を日付の型として読み込みます。\n",
    "第6章で日付を横軸にしたグラフを描くため、ここで日付の型にしておきます。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "c97b9c6f",
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.read_csv(\"sales.csv\", parse_dates=[\"date\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b0e7a14f",
   "metadata": {},
   "source": [
    "`FileNotFoundError`と表示された場合は、ファイルが見つからないことを示しています。\n",
    "`sales.csv`が作業フォルダの直下にあるか、ファイル名が`sales (1).csv`などに変わっていないかを確認してください。\n",
    "\n",
    "続けて、読み込んだデータの概要を確認します。\n",
    "加工する前に、どのような列があるか、何行あるか、値の抜けがないかなどを確かめます。\n",
    "\n",
    "`df`だけを実行すると、DataFrameが表示されます。\n",
    "行が多い場合は、途中の行が「...」で省略され、先頭と末尾の行だけが表示されます。\n",
    "表の下には、行の数と列の数が表示されます。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "331f2d06",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>date</th>\n",
       "      <th>store</th>\n",
       "      <th>item</th>\n",
       "      <th>quantity</th>\n",
       "      <th>price</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>東京店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>38.0</td>\n",
       "      <td>400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>東京店</td>\n",
       "      <td>紅茶</td>\n",
       "      <td>24.0</td>\n",
       "      <td>450</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>東京店</td>\n",
       "      <td>ケーキ</td>\n",
       "      <td>19.0</td>\n",
       "      <td>500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>大阪店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>35.0</td>\n",
       "      <td>400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>大阪店</td>\n",
       "      <td>紅茶</td>\n",
       "      <td>20.0</td>\n",
       "      <td>450</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>265</th>\n",
       "      <td>2026-04-30</td>\n",
       "      <td>大阪店</td>\n",
       "      <td>紅茶</td>\n",
       "      <td>18.0</td>\n",
       "      <td>450</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>266</th>\n",
       "      <td>2026-04-30</td>\n",
       "      <td>大阪店</td>\n",
       "      <td>ケーキ</td>\n",
       "      <td>14.0</td>\n",
       "      <td>500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>267</th>\n",
       "      <td>2026-04-30</td>\n",
       "      <td>名古屋店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>22.0</td>\n",
       "      <td>400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>268</th>\n",
       "      <td>2026-04-30</td>\n",
       "      <td>名古屋店</td>\n",
       "      <td>紅茶</td>\n",
       "      <td>17.0</td>\n",
       "      <td>450</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>269</th>\n",
       "      <td>2026-04-30</td>\n",
       "      <td>名古屋店</td>\n",
       "      <td>ケーキ</td>\n",
       "      <td>11.0</td>\n",
       "      <td>500</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>270 rows × 5 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "          date store  item  quantity  price\n",
       "0   2026-04-01   東京店  コーヒー      38.0    400\n",
       "1   2026-04-01   東京店    紅茶      24.0    450\n",
       "2   2026-04-01   東京店   ケーキ      19.0    500\n",
       "3   2026-04-01   大阪店  コーヒー      35.0    400\n",
       "4   2026-04-01   大阪店    紅茶      20.0    450\n",
       "..         ...   ...   ...       ...    ...\n",
       "265 2026-04-30   大阪店    紅茶      18.0    450\n",
       "266 2026-04-30   大阪店   ケーキ      14.0    500\n",
       "267 2026-04-30  名古屋店  コーヒー      22.0    400\n",
       "268 2026-04-30  名古屋店    紅茶      17.0    450\n",
       "269 2026-04-30  名古屋店   ケーキ      11.0    500\n",
       "\n",
       "[270 rows x 5 columns]"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5fd37352",
   "metadata": {},
   "source": [
    "`head()`メソッドは先頭の5行を表示します。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "a0e127c1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>date</th>\n",
       "      <th>store</th>\n",
       "      <th>item</th>\n",
       "      <th>quantity</th>\n",
       "      <th>price</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>東京店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>38.0</td>\n",
       "      <td>400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>東京店</td>\n",
       "      <td>紅茶</td>\n",
       "      <td>24.0</td>\n",
       "      <td>450</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>東京店</td>\n",
       "      <td>ケーキ</td>\n",
       "      <td>19.0</td>\n",
       "      <td>500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>大阪店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>35.0</td>\n",
       "      <td>400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>大阪店</td>\n",
       "      <td>紅茶</td>\n",
       "      <td>20.0</td>\n",
       "      <td>450</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        date store  item  quantity  price\n",
       "0 2026-04-01   東京店  コーヒー      38.0    400\n",
       "1 2026-04-01   東京店    紅茶      24.0    450\n",
       "2 2026-04-01   東京店   ケーキ      19.0    500\n",
       "3 2026-04-01   大阪店  コーヒー      35.0    400\n",
       "4 2026-04-01   大阪店    紅茶      20.0    450"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "291d113c",
   "metadata": {},
   "source": [
    "同様に、`tail()`メソッドは末尾の5行を表示します。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "4db22230",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>date</th>\n",
       "      <th>store</th>\n",
       "      <th>item</th>\n",
       "      <th>quantity</th>\n",
       "      <th>price</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>265</th>\n",
       "      <td>2026-04-30</td>\n",
       "      <td>大阪店</td>\n",
       "      <td>紅茶</td>\n",
       "      <td>18.0</td>\n",
       "      <td>450</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>266</th>\n",
       "      <td>2026-04-30</td>\n",
       "      <td>大阪店</td>\n",
       "      <td>ケーキ</td>\n",
       "      <td>14.0</td>\n",
       "      <td>500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>267</th>\n",
       "      <td>2026-04-30</td>\n",
       "      <td>名古屋店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>22.0</td>\n",
       "      <td>400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>268</th>\n",
       "      <td>2026-04-30</td>\n",
       "      <td>名古屋店</td>\n",
       "      <td>紅茶</td>\n",
       "      <td>17.0</td>\n",
       "      <td>450</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>269</th>\n",
       "      <td>2026-04-30</td>\n",
       "      <td>名古屋店</td>\n",
       "      <td>ケーキ</td>\n",
       "      <td>11.0</td>\n",
       "      <td>500</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "          date store  item  quantity  price\n",
       "265 2026-04-30   大阪店    紅茶      18.0    450\n",
       "266 2026-04-30   大阪店   ケーキ      14.0    500\n",
       "267 2026-04-30  名古屋店  コーヒー      22.0    400\n",
       "268 2026-04-30  名古屋店    紅茶      17.0    450\n",
       "269 2026-04-30  名古屋店   ケーキ      11.0    500"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.tail()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bd2fcc62",
   "metadata": {},
   "source": [
    "`describe()`メソッドは、数値の列の統計（件数、平均、標準偏差、最小、最大など）を表示します。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "ea8e35c6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>date</th>\n",
       "      <th>quantity</th>\n",
       "      <th>price</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>270</td>\n",
       "      <td>268.000000</td>\n",
       "      <td>270.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>2026-04-15 12:00:00</td>\n",
       "      <td>20.884328</td>\n",
       "      <td>450.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>2026-04-01 00:00:00</td>\n",
       "      <td>9.000000</td>\n",
       "      <td>400.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>2026-04-08 00:00:00</td>\n",
       "      <td>14.000000</td>\n",
       "      <td>400.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>2026-04-15 12:00:00</td>\n",
       "      <td>19.000000</td>\n",
       "      <td>450.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>2026-04-23 00:00:00</td>\n",
       "      <td>25.000000</td>\n",
       "      <td>500.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>2026-04-30 00:00:00</td>\n",
       "      <td>43.000000</td>\n",
       "      <td>500.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>NaN</td>\n",
       "      <td>8.376312</td>\n",
       "      <td>40.900641</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                      date    quantity       price\n",
       "count                  270  268.000000  270.000000\n",
       "mean   2026-04-15 12:00:00   20.884328  450.000000\n",
       "min    2026-04-01 00:00:00    9.000000  400.000000\n",
       "25%    2026-04-08 00:00:00   14.000000  400.000000\n",
       "50%    2026-04-15 12:00:00   19.000000  450.000000\n",
       "75%    2026-04-23 00:00:00   25.000000  500.000000\n",
       "max    2026-04-30 00:00:00   43.000000  500.000000\n",
       "std                    NaN    8.376312   40.900641"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.describe()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a9c8cc02",
   "metadata": {},
   "source": [
    "日付の列（`date`）も表示され、最小（`min`）と最大（`max`）でデータの期間が分かります。\n",
    "\n",
    "```{table} describe()メソッドの出力の意味\n",
    "| 項目 | 意味 |\n",
    "|---|---|\n",
    "| `count` | データの件数（欠損値（後述）などは件数から除外される） |\n",
    "| `mean` | 平均値 |\n",
    "| `min` | 最小値 |\n",
    "| `25%` | 小さい方から25%の位置の値 |\n",
    "| `50%` | 中央値（小さい方から50%の位置の値） |\n",
    "| `75%` | 小さい方から75%の位置の値 |\n",
    "| `max` | 最大値 |\n",
    "| `std` | 標準偏差（値のばらつきの大きさ） |\n",
    "```\n",
    "\n",
    "`shape`は、行の数と列の数を表示します。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "cf65ef90",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(270, 5)"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f99fddce",
   "metadata": {},
   "source": [
    "## データを抽出する\n",
    "\n",
    "```{note}\n",
    "コードを実行した結果が資料と違うときやエラーになったときは、「売上データを読み込む」のセルから順に実行し直してください。\n",
    "```\n",
    "\n",
    "DataFrameから、必要な列や行だけを取り出します。\n",
    "\n",
    "列名を`[]`で指定すると、1つの列をSeriesとして取り出せます。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "db7d3f91",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0       東京店\n",
       "1       東京店\n",
       "2       東京店\n",
       "3       大阪店\n",
       "4       大阪店\n",
       "       ... \n",
       "265     大阪店\n",
       "266     大阪店\n",
       "267    名古屋店\n",
       "268    名古屋店\n",
       "269    名古屋店\n",
       "Name: store, Length: 270, dtype: str"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df[\"store\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9f8550a0",
   "metadata": {},
   "source": [
    "出力の最後の`dtype: str`は、この列の型が文字列型（`str`）であることを表します。\n",
    "pandas 3.0からは文字列の列が`str`型と表示されます（それ以前のバージョンでは`object`型と表示されます）。\n",
    "\n",
    "列名のリストを指定すると、複数の列をDataFrameとして取り出せます。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "f1a7bdea",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>store</th>\n",
       "      <th>quantity</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>東京店</td>\n",
       "      <td>38.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>東京店</td>\n",
       "      <td>24.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>東京店</td>\n",
       "      <td>19.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>大阪店</td>\n",
       "      <td>35.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>大阪店</td>\n",
       "      <td>20.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>265</th>\n",
       "      <td>大阪店</td>\n",
       "      <td>18.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>266</th>\n",
       "      <td>大阪店</td>\n",
       "      <td>14.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>267</th>\n",
       "      <td>名古屋店</td>\n",
       "      <td>22.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>268</th>\n",
       "      <td>名古屋店</td>\n",
       "      <td>17.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>269</th>\n",
       "      <td>名古屋店</td>\n",
       "      <td>11.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>270 rows × 2 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "    store  quantity\n",
       "0     東京店      38.0\n",
       "1     東京店      24.0\n",
       "2     東京店      19.0\n",
       "3     大阪店      35.0\n",
       "4     大阪店      20.0\n",
       "..    ...       ...\n",
       "265   大阪店      18.0\n",
       "266   大阪店      14.0\n",
       "267  名古屋店      22.0\n",
       "268  名古屋店      17.0\n",
       "269  名古屋店      11.0\n",
       "\n",
       "[270 rows x 2 columns]"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df[[\"store\", \"quantity\"]]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f675abc2",
   "metadata": {},
   "source": [
    "`[]`に`開始:終了`の形でスライスと同じ表記を指定すると、行を範囲で取り出せます。\n",
    "スライスと同様、開始の行は含まれ、終了の行は含まれません。\n",
    "開始や終了の数値を省略すると、それぞれ先頭から、末尾までを取り出します。\n",
    "次のコードでは、先頭の2行（0行目と1行目）を取り出します。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "298f0dec",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>date</th>\n",
       "      <th>store</th>\n",
       "      <th>item</th>\n",
       "      <th>quantity</th>\n",
       "      <th>price</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>東京店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>38.0</td>\n",
       "      <td>400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>東京店</td>\n",
       "      <td>紅茶</td>\n",
       "      <td>24.0</td>\n",
       "      <td>450</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        date store  item  quantity  price\n",
       "0 2026-04-01   東京店  コーヒー      38.0    400\n",
       "1 2026-04-01   東京店    紅茶      24.0    450"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df[:2]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a85286dd",
   "metadata": {},
   "source": [
    "### locとiloc\n",
    "\n",
    "行と列を指定して取り出すには`loc`や`iloc`を使います。\n",
    "どちらも`[行, 列]`の形で指定し、`:`で範囲を指定できます。\n",
    "\n",
    "`loc`は、インデックスのラベルと列名で指定します。\n",
    "次のコードでは、インデックスが0から2までの行の、`store`から`quantity`までの列を取り出します。\n",
    "`loc`では、範囲の終わりのラベル（2と`quantity`）も含まれます。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "e76fa07d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>store</th>\n",
       "      <th>item</th>\n",
       "      <th>quantity</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>東京店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>38.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>東京店</td>\n",
       "      <td>紅茶</td>\n",
       "      <td>24.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>東京店</td>\n",
       "      <td>ケーキ</td>\n",
       "      <td>19.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  store  item  quantity\n",
       "0   東京店  コーヒー      38.0\n",
       "1   東京店    紅茶      24.0\n",
       "2   東京店   ケーキ      19.0"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.loc[0:2, \"store\":\"quantity\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "77ef6863",
   "metadata": {},
   "source": [
    "`iloc`は、行のインデックス番号と列のカラム番号で指定します。どちらも0から始まる連番です。\n",
    "次のコードでは、0行目と1行目の、1列目から3列目（`store`、`item`、`quantity`）を取り出します。\n",
    "`iloc`では、`[]`の範囲の指定と同じく、範囲の終わりは含まれません。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "aef24bc2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>store</th>\n",
       "      <th>item</th>\n",
       "      <th>quantity</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>東京店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>38.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>東京店</td>\n",
       "      <td>紅茶</td>\n",
       "      <td>24.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  store  item  quantity\n",
       "0   東京店  コーヒー      38.0\n",
       "1   東京店    紅茶      24.0"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.iloc[0:2, 1:4]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6f613633",
   "metadata": {},
   "source": [
    "### 条件で抽出\n",
    "\n",
    "列に対して条件を書くと、行ごとに条件を満たすかが`True`または`False`で返されます。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "37f02d46",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0       True\n",
       "1       True\n",
       "2       True\n",
       "3      False\n",
       "4      False\n",
       "       ...  \n",
       "265    False\n",
       "266    False\n",
       "267    False\n",
       "268    False\n",
       "269    False\n",
       "Name: store, Length: 270, dtype: bool"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df[\"store\"] == \"東京店\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c9e9204f",
   "metadata": {},
   "source": [
    "この条件をDataFrameの`[]`に入れると、`True`の行だけを抽出できます。\n",
    "次のコードでは、東京店の行だけを取り出して`df_tokyo`に代入します。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "d2b37243",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>date</th>\n",
       "      <th>store</th>\n",
       "      <th>item</th>\n",
       "      <th>quantity</th>\n",
       "      <th>price</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>東京店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>38.0</td>\n",
       "      <td>400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>東京店</td>\n",
       "      <td>紅茶</td>\n",
       "      <td>24.0</td>\n",
       "      <td>450</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>東京店</td>\n",
       "      <td>ケーキ</td>\n",
       "      <td>19.0</td>\n",
       "      <td>500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>2026-04-02</td>\n",
       "      <td>東京店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>38.0</td>\n",
       "      <td>400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>2026-04-02</td>\n",
       "      <td>東京店</td>\n",
       "      <td>紅茶</td>\n",
       "      <td>25.0</td>\n",
       "      <td>450</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>2026-04-02</td>\n",
       "      <td>東京店</td>\n",
       "      <td>ケーキ</td>\n",
       "      <td>14.0</td>\n",
       "      <td>500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>2026-04-03</td>\n",
       "      <td>東京店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>33.0</td>\n",
       "      <td>400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>2026-04-03</td>\n",
       "      <td>東京店</td>\n",
       "      <td>紅茶</td>\n",
       "      <td>25.0</td>\n",
       "      <td>450</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20</th>\n",
       "      <td>2026-04-03</td>\n",
       "      <td>東京店</td>\n",
       "      <td>ケーキ</td>\n",
       "      <td>19.0</td>\n",
       "      <td>500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>27</th>\n",
       "      <td>2026-04-04</td>\n",
       "      <td>東京店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>29.0</td>\n",
       "      <td>400</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "         date store  item  quantity  price\n",
       "0  2026-04-01   東京店  コーヒー      38.0    400\n",
       "1  2026-04-01   東京店    紅茶      24.0    450\n",
       "2  2026-04-01   東京店   ケーキ      19.0    500\n",
       "9  2026-04-02   東京店  コーヒー      38.0    400\n",
       "10 2026-04-02   東京店    紅茶      25.0    450\n",
       "11 2026-04-02   東京店   ケーキ      14.0    500\n",
       "18 2026-04-03   東京店  コーヒー      33.0    400\n",
       "19 2026-04-03   東京店    紅茶      25.0    450\n",
       "20 2026-04-03   東京店   ケーキ      19.0    500\n",
       "27 2026-04-04   東京店  コーヒー      29.0    400"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_tokyo = df[df[\"store\"] == \"東京店\"]\n",
    "df_tokyo.head(10)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4d67c40e",
   "metadata": {},
   "source": [
    "取り出したDataFrameのインデックスは、元となったDataFrameのインデックス値のままで、間が飛ばされていることがわかります。\n",
    "そのため、`df_tokyo`では`loc`と`iloc`に同じ数字を指定しても、違う行が選ばれます。\n",
    "`loc`ではインデックスが9の行が選ばれます。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "6a2c2a68",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "date        2026-04-02 00:00:00\n",
       "store                       東京店\n",
       "item                       コーヒー\n",
       "quantity                   38.0\n",
       "price                       400\n",
       "Name: 9, dtype: object"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_tokyo.loc[9]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "58ad2fc2",
   "metadata": {},
   "source": [
    "`iloc`では上から10番目（0から数えて9番目）の行が選ばれます。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "2ebc5a95",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "date        2026-04-04 00:00:00\n",
       "store                       東京店\n",
       "item                       コーヒー\n",
       "quantity                   29.0\n",
       "price                       400\n",
       "Name: 27, dtype: object"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_tokyo.iloc[9]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "93b36440",
   "metadata": {},
   "source": [
    "## データを整形する\n",
    "\n",
    "分析しやすいように、データの並び順や値を整えます。\n",
    "\n",
    "`sort_values()`メソッドは、指定した列の値で行を並べ替えます。\n",
    "デフォルトでは昇順で並べ替えが行われ、`ascending=False`を指定すると降順に並べ替えます。\n",
    "次のコードでは、販売数の降順（多い順）に並べ替えを行い、その先頭5行を表示します。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "333ac989",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>date</th>\n",
       "      <th>store</th>\n",
       "      <th>item</th>\n",
       "      <th>quantity</th>\n",
       "      <th>price</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>99</th>\n",
       "      <td>2026-04-12</td>\n",
       "      <td>東京店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>43.0</td>\n",
       "      <td>400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>126</th>\n",
       "      <td>2026-04-15</td>\n",
       "      <td>東京店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>43.0</td>\n",
       "      <td>400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>243</th>\n",
       "      <td>2026-04-28</td>\n",
       "      <td>東京店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>43.0</td>\n",
       "      <td>400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>261</th>\n",
       "      <td>2026-04-30</td>\n",
       "      <td>東京店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>42.0</td>\n",
       "      <td>400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>117</th>\n",
       "      <td>2026-04-14</td>\n",
       "      <td>東京店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>42.0</td>\n",
       "      <td>400</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "          date store  item  quantity  price\n",
       "99  2026-04-12   東京店  コーヒー      43.0    400\n",
       "126 2026-04-15   東京店  コーヒー      43.0    400\n",
       "243 2026-04-28   東京店  コーヒー      43.0    400\n",
       "261 2026-04-30   東京店  コーヒー      42.0    400\n",
       "117 2026-04-14   東京店  コーヒー      42.0    400"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.sort_values(\"quantity\", ascending=False).head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d4f15089",
   "metadata": {},
   "source": [
    "並べ替えた結果を変数に代入していないため、元の`df`の並び順は変わりません。\n",
    "\n",
    "### 欠損値の処理\n",
    "\n",
    "値が入っていないことを**欠損値**と呼びます。\n",
    "実際のデータでは、記録漏れなどで欠損値が含まれることがよくあります。\n",
    "欠損値があると計算の結果が正しくならないため、分析の前に確認して対処します。\n",
    "\n",
    "`isna()`メソッドは、値が欠損値かどうかを`True`または`False`で返します。\n",
    "続けて`sum()`メソッドを使うと、列ごとに欠損値の数を数えられます。\n",
    "なお、`isnull()`メソッドは`isna()`メソッドと同じ働きをします。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "9b70aaab",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "date        0\n",
       "store       0\n",
       "item        0\n",
       "quantity    2\n",
       "price       0\n",
       "dtype: int64"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.isna().sum()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "84ccaacf",
   "metadata": {},
   "source": [
    "`quantity`の列に欠損値があります。\n",
    "欠損値のある行を取り出して確認します。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "0f28c6b7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>date</th>\n",
       "      <th>store</th>\n",
       "      <th>item</th>\n",
       "      <th>quantity</th>\n",
       "      <th>price</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>23</th>\n",
       "      <td>2026-04-03</td>\n",
       "      <td>大阪店</td>\n",
       "      <td>ケーキ</td>\n",
       "      <td>NaN</td>\n",
       "      <td>500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>69</th>\n",
       "      <td>2026-04-08</td>\n",
       "      <td>名古屋店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>NaN</td>\n",
       "      <td>400</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "         date store  item  quantity  price\n",
       "23 2026-04-03   大阪店   ケーキ       NaN    500\n",
       "69 2026-04-08  名古屋店  コーヒー       NaN    400"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df[df[\"quantity\"].isna()]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "501e6c05",
   "metadata": {},
   "source": [
    "欠損値は`NaN`と表示されます。\n",
    "`NaN`はNot a Numberの略で非数を表します。\n",
    "並べ替えの結果で`quantity`が`40.0`のように小数で表示されていたのは、欠損値があるためです。\n",
    "欠損値を含む列は、整数の列でも小数の型になります。\n",
    "\n",
    "欠損値の対処には、欠損値が存在する行を削除する方法と、欠損値をほかの値に置き換える方法があります。\n",
    "`dropna()`メソッドは、欠損値のある行を削除します。\n",
    "ここでは行の数が減ることを確かめるだけで、元の`df`は変えません。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "eed7b59b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(268, 5)"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.dropna().shape"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "67361690",
   "metadata": {},
   "source": [
    "ここでは、販売数の欠損値を0に置き換えます。\n",
    "`fillna()`メソッドで欠損値を0に置き換え、その結果を`quantity`列に代入します。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "723dfe24",
   "metadata": {},
   "outputs": [],
   "source": [
    "df[\"quantity\"] = df[\"quantity\"].fillna(0)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dbd2d49c",
   "metadata": {},
   "source": [
    "```{note}\n",
    "書籍やWebの記事には、`df[\"quantity\"].fillna(0, inplace=True)`のように`inplace=True`を指定する例があります。\n",
    "pandas 3.0では、この書き方では元の`df`が変わりません。\n",
    "この節のように、結果を列に代入してください。\n",
    "```\n",
    "\n",
    "欠損値がなくなったので、`astype()`メソッドで`quantity`列を整数（`int`）型に変換します。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "fa87fd3a",
   "metadata": {},
   "outputs": [],
   "source": [
    "df[\"quantity\"] = df[\"quantity\"].astype(int)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d7095acc",
   "metadata": {},
   "source": [
    "欠損値だった2つの行を`loc`で指定し、`quantity`列の値が0に置き換わったことを確かめます。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "3098d488",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>date</th>\n",
       "      <th>store</th>\n",
       "      <th>item</th>\n",
       "      <th>quantity</th>\n",
       "      <th>price</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>23</th>\n",
       "      <td>2026-04-03</td>\n",
       "      <td>大阪店</td>\n",
       "      <td>ケーキ</td>\n",
       "      <td>0</td>\n",
       "      <td>500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>69</th>\n",
       "      <td>2026-04-08</td>\n",
       "      <td>名古屋店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>0</td>\n",
       "      <td>400</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "         date store  item  quantity  price\n",
       "23 2026-04-03   大阪店   ケーキ         0    500\n",
       "69 2026-04-08  名古屋店  コーヒー         0    400"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.loc[[23, 69]]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "146b6e7e",
   "metadata": {},
   "source": [
    "最後に、販売数と単価を掛けて、売上金額の列（`amount`）をDataFrameに追加します。\n",
    "列どうしの計算は全ての行に対して行われ、全ての`amount`列に計算結果が入ります。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "2318051a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>date</th>\n",
       "      <th>store</th>\n",
       "      <th>item</th>\n",
       "      <th>quantity</th>\n",
       "      <th>price</th>\n",
       "      <th>amount</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>東京店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>38</td>\n",
       "      <td>400</td>\n",
       "      <td>15200</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>東京店</td>\n",
       "      <td>紅茶</td>\n",
       "      <td>24</td>\n",
       "      <td>450</td>\n",
       "      <td>10800</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>東京店</td>\n",
       "      <td>ケーキ</td>\n",
       "      <td>19</td>\n",
       "      <td>500</td>\n",
       "      <td>9500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>大阪店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>35</td>\n",
       "      <td>400</td>\n",
       "      <td>14000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>大阪店</td>\n",
       "      <td>紅茶</td>\n",
       "      <td>20</td>\n",
       "      <td>450</td>\n",
       "      <td>9000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        date store  item  quantity  price  amount\n",
       "0 2026-04-01   東京店  コーヒー        38    400   15200\n",
       "1 2026-04-01   東京店    紅茶        24    450   10800\n",
       "2 2026-04-01   東京店   ケーキ        19    500    9500\n",
       "3 2026-04-01   大阪店  コーヒー        35    400   14000\n",
       "4 2026-04-01   大阪店    紅茶        20    450    9000"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df[\"amount\"] = df[\"quantity\"] * df[\"price\"]\n",
    "df.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3440ea03",
   "metadata": {},
   "source": [
    "## データを連結する\n",
    "\n",
    "ここでは、複数のDataFrameを1つにまとめる**連結**について説明します。\n",
    "\n",
    "「売上データを読み込む」でダウンロードした翌月の売上（`sales_next_month.csv`）を読み込み`df_next_month`に代入します。\n",
    "CSVファイルには2026年5月1日の売上が3行入っています。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "abdfab6f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>date</th>\n",
       "      <th>store</th>\n",
       "      <th>item</th>\n",
       "      <th>quantity</th>\n",
       "      <th>price</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2026-05-01</td>\n",
       "      <td>東京店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>36</td>\n",
       "      <td>400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2026-05-01</td>\n",
       "      <td>大阪店</td>\n",
       "      <td>紅茶</td>\n",
       "      <td>19</td>\n",
       "      <td>450</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2026-05-01</td>\n",
       "      <td>名古屋店</td>\n",
       "      <td>ケーキ</td>\n",
       "      <td>12</td>\n",
       "      <td>500</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        date store  item  quantity  price\n",
       "0 2026-05-01   東京店  コーヒー        36    400\n",
       "1 2026-05-01   大阪店    紅茶        19    450\n",
       "2 2026-05-01  名古屋店   ケーキ        12    500"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_next_month = pd.read_csv(\"sales_next_month.csv\", parse_dates=[\"date\"])\n",
    "df_next_month"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8851908b",
   "metadata": {},
   "source": [
    "`FileNotFoundError`と表示された場合は、「売上データを読み込む」と同じく、ファイルの場所と名前を確認してください。\n",
    "\n",
    "`pd.concat()`関数にDataFrameのリストを渡すと、指定されたDataFrameを行方向に連結します。\n",
    "`ignore_index=True`を指定すると、インデックスを0から振り直します。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "d973f50d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>date</th>\n",
       "      <th>store</th>\n",
       "      <th>item</th>\n",
       "      <th>quantity</th>\n",
       "      <th>price</th>\n",
       "      <th>amount</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>268</th>\n",
       "      <td>2026-04-30</td>\n",
       "      <td>名古屋店</td>\n",
       "      <td>紅茶</td>\n",
       "      <td>17</td>\n",
       "      <td>450</td>\n",
       "      <td>7650.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>269</th>\n",
       "      <td>2026-04-30</td>\n",
       "      <td>名古屋店</td>\n",
       "      <td>ケーキ</td>\n",
       "      <td>11</td>\n",
       "      <td>500</td>\n",
       "      <td>5500.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>270</th>\n",
       "      <td>2026-05-01</td>\n",
       "      <td>東京店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>36</td>\n",
       "      <td>400</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>271</th>\n",
       "      <td>2026-05-01</td>\n",
       "      <td>大阪店</td>\n",
       "      <td>紅茶</td>\n",
       "      <td>19</td>\n",
       "      <td>450</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>272</th>\n",
       "      <td>2026-05-01</td>\n",
       "      <td>名古屋店</td>\n",
       "      <td>ケーキ</td>\n",
       "      <td>12</td>\n",
       "      <td>500</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "          date store  item  quantity  price  amount\n",
       "268 2026-04-30  名古屋店    紅茶        17    450  7650.0\n",
       "269 2026-04-30  名古屋店   ケーキ        11    500  5500.0\n",
       "270 2026-05-01   東京店  コーヒー        36    400     NaN\n",
       "271 2026-05-01   大阪店    紅茶        19    450     NaN\n",
       "272 2026-05-01  名古屋店   ケーキ        12    500     NaN"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.concat([df, df_next_month], ignore_index=True).tail()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "45856493",
   "metadata": {},
   "source": [
    "売上の後ろに翌月の売上の3行が連結されました。\n",
    "翌月の売上には`amount`の列がないため、`amount`は欠損値になります。\n",
    "この結果は後の節では使わないため、代入していません。\n",
    "\n",
    "`axis=1`を指定すると、DataFrameを列方向に連結します。\n",
    "例として、売上の先頭の3行を`date`と`store`の列、`item`と`quantity`の列の2つのDataFrameに分けます。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "a9231d4a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>date</th>\n",
       "      <th>store</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>東京店</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>東京店</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>東京店</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        date store\n",
       "0 2026-04-01   東京店\n",
       "1 2026-04-01   東京店\n",
       "2 2026-04-01   東京店"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "left = df[[\"date\", \"store\"]].head(3)\n",
    "left"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "fa0f3bb9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>item</th>\n",
       "      <th>quantity</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>コーヒー</td>\n",
       "      <td>38</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>紅茶</td>\n",
       "      <td>24</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>ケーキ</td>\n",
       "      <td>19</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   item  quantity\n",
       "0  コーヒー        38\n",
       "1    紅茶        24\n",
       "2   ケーキ        19"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "right = df[[\"item\", \"quantity\"]].head(3)\n",
    "right"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3320906d",
   "metadata": {},
   "source": [
    "2つのDataFrameを横に連結すると、元の4列の表に戻ります。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "856cb54d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>date</th>\n",
       "      <th>store</th>\n",
       "      <th>item</th>\n",
       "      <th>quantity</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>東京店</td>\n",
       "      <td>コーヒー</td>\n",
       "      <td>38</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>東京店</td>\n",
       "      <td>紅茶</td>\n",
       "      <td>24</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2026-04-01</td>\n",
       "      <td>東京店</td>\n",
       "      <td>ケーキ</td>\n",
       "      <td>19</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        date store  item  quantity\n",
       "0 2026-04-01   東京店  コーヒー        38\n",
       "1 2026-04-01   東京店    紅茶        24\n",
       "2 2026-04-01   東京店   ケーキ        19"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.concat([left, right], axis=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "67456e28",
   "metadata": {},
   "source": [
    "## データを集計する\n",
    "\n",
    "**集計**は、データをグループごとにまとめて、合計や平均などを計算することです。\n",
    "`groupby()`メソッドに列名を指定すると、その列の値ごとにグループに分けます。\n",
    "次のコードでは、店舗ごとにグループ化し、売上金額（`amount`）を`sum()`メソッドで合計します。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "598b9b7c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "store\n",
       "名古屋店    641850\n",
       "大阪店     815050\n",
       "東京店     988500\n",
       "Name: amount, dtype: int64"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.groupby(\"store\")[\"amount\"].sum()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7fe63b31",
   "metadata": {},
   "source": [
    "## さまざまなファイル形式の読み込みと書き出し\n",
    "\n",
    "pandasは、CSVファイルのほかにもさまざまなファイル形式の読み込みと書き出しに対応しています。\n",
    "読み込みには`pd.read_csv()`関数のような`read_`からはじまるpandasの関数を、書き出しには`to_csv()`メソッドのような`to_`からはじまるDataFrameのメソッドを使います。\n",
    "ファイル形式によっては、pandasのほかに追加のライブラリのインストールが必要です。\n",
    "\n",
    "```{table} 代表的なファイル形式と読み込み・書き出しの関数・メソッド\n",
    "| ファイル形式 | 読み込み | 書き出し | 追加のライブラリ |\n",
    "|---|---|---|---|\n",
    "| CSV | `pd.read_csv()` | `to_csv()` | 不要 |\n",
    "| Excel | `pd.read_excel()` | `to_excel()` | openpyxl |\n",
    "| JSON | `pd.read_json()` | `to_json()` | 不要 |\n",
    "| Parquet | `pd.read_parquet()` | `to_parquet()` | pyarrow |\n",
    "| HTML | `pd.read_html()` | `to_html()` | 読み込みにlxmlなど |\n",
    "```\n",
    "\n",
    "最後に、加工したデータを`to_csv()`メソッドでCSVファイルに書き出します。\n",
    "このファイルは第6章でグラフを作るときに使います。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "835d2056",
   "metadata": {},
   "outputs": [],
   "source": [
    "df.to_csv(\"sales_clean.csv\", index=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "202c2f4a",
   "metadata": {},
   "source": [
    "作業フォルダに`sales_clean.csv`ができます。\n",
    "この章のコードを実行できなかった場合は、{download}`sales_clean.csv`をダウンロードして作業フォルダに置いてください。\n",
    "\n",
    "## この章のまとめ\n",
    "\n",
    "この章では以下を行いました。\n",
    "\n",
    "```{table} この章で行ったこと\n",
    "| 節 | 行ったこと | 使った関数・メソッドなど |\n",
    "|---|---|---|\n",
    "| SeriesとDataFrame | SeriesとDataFrameの作成、インデックスと列名の確認 | `pd.Series()`、`pd.DataFrame()`、`index`、`columns` |\n",
    "| CSVファイルの書き出しと読み込み | DataFrameのCSVファイルへの書き出しと読み込み | `to_csv()`、`pd.read_csv()` |\n",
    "| 売上データを読み込む | 売上データの読み込みと概要の確認 | `pd.read_csv()`、`head()`、`tail()`、`describe()`、`shape` |\n",
    "| データを抽出する | さまざまな方法で指定した列や行を抽出 | `[]`、`loc`、`iloc` |\n",
    "| データを整形する | 並べ替え、欠損値の処理、列の追加 | `sort_values()`、`isna()`、`dropna()`、`fillna()`、`astype()` |\n",
    "| データを連結する | DataFrameを行方向または列方向に連結 | `pd.concat()` |\n",
    "| データを集計する | 店舗ごとの売上金額の集計 | `groupby()`、`sum()` |\n",
    "| さまざまなファイル形式の読み込みと書き出し | ファイル形式ごとの読み込みと書き出しの関数・メソッドの確認 | `pd.read_excel()`、`to_excel()`など |\n",
    "```\n",
    "\n",
    "次の第6章では、書き出した`sales_clean.csv`を使って、Matplotlibでさまざまなグラフを描画します。"
   ]
  }
 ],
 "metadata": {
  "file_format": "mystnb",
  "kernelspec": {
   "display_name": "Python 3",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.14.3"
  },
  "source_map": [
   6,
   34,
   36,
   46,
   49,
   55,
   57,
   63,
   66,
   71,
   73,
   77,
   79,
   90,
   92,
   117,
   120,
   152,
   154,
   166,
   168,
   172,
   174,
   178,
   180,
   184,
   186,
   205,
   207,
   219,
   221,
   228,
   230,
   237,
   239,
   250,
   252,
   258,
   260,
   266,
   268,
   273,
   276,
   282,
   284,
   288,
   290,
   300,
   302,
   316,
   318,
   323,
   325,
   336,
   338,
   343,
   345,
   355,
   357,
   361,
   363,
   368,
   371,
   380,
   383,
   390,
   392,
   401,
   406,
   409,
   413,
   415,
   423,
   425,
   446,
   448
  ]
 },
 "nbformat": 4,
 "nbformat_minor": 5
}