{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "data_wrangling.ipynb",
      "provenance": [],
      "collapsed_sections": [],
      "toc_visible": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "sxc9s6eS1fPE"
      },
      "source": [
        "# pandas入門＋推薦システムの例\n",
        "## 映画レビューデータを通したデータ処理演習\n",
        "参考サイト: [Collaborative Filtering for Movie Recommendations](https://keras.io/examples/structured_data/collaborative_filtering_movielens/)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "wFa1Hx9f2Z-_"
      },
      "source": [
        "## 全体の流れ\n",
        "CSV/TSV等のテキストファイルで用意された生のデータの読み込み方、そこから必要な項目を抽出するようなデータ処理、平均値・分散値を算出したりといった一般的な統計処理、グラフや分布図等の描画方法について学んでみましょう。\n",
        "\n",
        "なお、[MovieLens](http://files.grouplens.org/datasets/movielens/ml-latest-small-README.html)と呼ばれる映画レビューデータセットを元に、似ているユーザを探し出し、そのユーザが高評価を付けているまだ視聴していない映画を抽出する映画推薦の例も示します。重要なのは個々のコードを覚えることではなく、必要なことを自身で検索して探し出し、参考にして実装できるようになることです。\n",
        "\n",
        "例えば ``pandas cheat sheet`` ぐらいでググると[Pandas Cheat Sheet for Data Science in Python](https://www.datacamp.com/community/blog/python-pandas-cheat-sheet)が見つかります。[pandas 列抽出](https://www.google.com/search?client=safari&sxsrf=ALeKk028LUPdRcMxKct-InRUlXvrhXEgWw%3A1615257233990&source=hp&ei=kd5GYNueOvmSr7wP3_WNmAs&iflsig=AINFCbYAAAAAYEbsoREhVTNrmXyCWNHJNO6v4L0YKjwL&q=pandas+%E5%88%97%E6%8A%BD%E5%87%BA&oq=pandas+%E5%88%97%E6%8A%BD%E5%87%BA&gs_lcp=Cgdnd3Mtd2l6EAMyAggAMgIIADICCAAyAggAMgIIADoECAAQBDoICAAQsQMQgwE6BwgAELEDEAQ6CggAELEDEIMBEAQ6BQgAELEDOgYIABAEEAM6CAgAEAQQChAqOgYIABAEEAo6CAgAEAQQChAeOgUIIRCgAToGCAAQBBAeUKoGWOpzYNJ1aAlwAHgBgAHpAYgBhB-SAQY0LjMxLjGYAQCgAQGqAQdnd3Mtd2l6&sclient=gws-wiz&ved=0ahUKEwibq5qNlqLvAhV5yYsBHd96A7MQ4dUDCAw&uact=5)ならこういう結果が得られます。検索上手になろう。\n"
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## Pandas入門としての達成目標\n",
        "- スキル目標\n",
        "  - まずはpd.DataFrameの基本的な操作（概要参照、行や列の参照、変更、np.ndarrayからの型変換）、可視化（pd.plot）あたりを覚えよう。それ以外は cheat sheet なり、必要に応じて調べて使えれば十分です。\n",
        "- 本チュートリアル固有の目標\n",
        "  - 「データセットの準備」、「行や列を指定した簡易処理」、「大雑把に可視化してみる」までを使えるようになろう。\n",
        "  - 「テーブルを組み合わせてみる」以降は **オマケ** です。映画レビューのデータセットを元に具体的な推薦システムを作ってみる例です。興味のある人はコードを追いかけてみてください。"
      ],
      "metadata": {
        "id": "UELpKxValQz8"
      }
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "s3x0bqzR2c8C"
      },
      "source": [
        "## 本チュートリアルで利用しているパッケージ\n",
        "すべてを使いこなすのではなく、必要な時に必要なものを探し出せるようになろう。\n",
        "\n",
        "- Python標準モジュール\n",
        "  - [zipfile](https://docs.python.org/ja/3/library/zipfile.html): ZIPアーカイブの処理。\n",
        "  - [pathlib](https://docs.python.org/ja/3/library/pathlib.html): ファイルパス処理。\n",
        "  - [io](https://docs.python.org/ja/3/library/io.html): 入出力処理。\n",
        "- 外部パッケージ\n",
        "  - requests: HTTPライブラリ。\n",
        "    - [クイックスタート](https://requests-docs-ja.readthedocs.io/en/latest/user/quickstart/)\n",
        "  - numpy: 数値演算・行列演算ライブラリ。\n",
        "    - [quickstart](https://docs.scipy.org/doc/numpy/user/quickstart.html) | [tutorial](https://avinton.com/python-numpy-tutorial-japanese/)\n",
        "  - pandas: 表形式データ操作ライブラリ。\n",
        "    - [tutorial](https://pandas.pydata.org/pandas-docs/stable/tutorials.html) | [10 Minutes to pandas](https://pandas.pydata.org/pandas-docs/stable/10min.html)\n",
        "  - matplotlib: 可視化ライブラリ。\n",
        "    - [tutorial](https://matplotlib.org/stable/tutorials/index.html)\n",
        "  - seaborn: 可視化ライブラリ。\n",
        "    - [tutorial](https://seaborn.pydata.org/tutorial.html)\n",
        "- Linuxコマンド\n",
        "  - ls: ファイル一覧をリスト表示。Windowsのdir相当。\n",
        "  - tree: 階層構造を可視化。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "H3mLPkj41ZGZ"
      },
      "source": [
        "# Python標準モジュール\n",
        "#from zipfile import ZipFile\n",
        "from pathlib import Path\n",
        "import zipfile, io\n",
        "\n",
        "# 外部パッケージ\n",
        "import requests\n",
        "import pandas as pd\n",
        "import numpy as np\n",
        "import matplotlib.pyplot as plt\n",
        "import seaborn as sns\n"
      ],
      "execution_count": 1,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "gUJfGzg-VeOW"
      },
      "source": [
        "## データセットの準備"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "INXemu4gbp1J"
      },
      "source": [
        "### データセットのダウンロード\n",
        "今回利用するデータセットは [MovieLens](http://files.grouplens.org/datasets/movielens/ml-latest-small-README.html) の最小データセットを利用する。MovieLensは、視聴者による映画に対する5点満点のレビューを収集して構築したものであり、「ユーザ1番は映画500番に対して4点を付けた」というデータの集合になっている。またユーザの嗜好や映画の属性についてもある程度判断するための情報として、ユーザは年齢・性別、映画はタイトル・カテゴリ・出版年が付与されている。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "h7lDxSgMwTuN",
        "outputId": "5beb3d6b-70ec-46ec-a90e-f99821e2e4ce"
      },
      "source": [
        "!apt install tree\n",
        "\n",
        "movielens_zipfile_url = \"http://files.grouplens.org/datasets/movielens/ml-latest-small.zip\"\n",
        "save_path = \"./\"\n",
        "r = requests.get(movielens_zipfile_url)\n",
        "print(r)\n",
        "print(type(r))\n",
        "print(r.content)\n",
        "\n",
        "zfile = zipfile.ZipFile(io.BytesIO(r.content))\n",
        "zfile.extractall(save_path)\n",
        "\n",
        "!ls\n",
        "!ls ml-latest-small/*\n",
        "!tree"
      ],
      "execution_count": 2,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Reading package lists... Done\n",
            "Building dependency tree       \n",
            "Reading state information... Done\n",
            "The following NEW packages will be installed:\n",
            "  tree\n",
            "0 upgraded, 1 newly installed, 0 to remove and 39 not upgraded.\n",
            "Need to get 40.7 kB of archives.\n",
            "After this operation, 105 kB of additional disk space will be used.\n",
            "Get:1 http://archive.ubuntu.com/ubuntu bionic/universe amd64 tree amd64 1.7.0-5 [40.7 kB]\n",
            "Fetched 40.7 kB in 0s (128 kB/s)\n",
            "Selecting previously unselected package tree.\n",
            "(Reading database ... 155335 files and directories currently installed.)\n",
            "Preparing to unpack .../tree_1.7.0-5_amd64.deb ...\n",
            "Unpacking tree (1.7.0-5) ...\n",
            "Setting up tree (1.7.0-5) ...\n",
            "Processing triggers for man-db (2.8.3-2ubuntu0.1) ...\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "IOPub data rate exceeded.\n",
            "The notebook server will temporarily stop sending output\n",
            "to the client in order to avoid crashing it.\n",
            "To change this limit, set the config variable\n",
            "`--NotebookApp.iopub_data_rate_limit`.\n",
            "\n",
            "Current values:\n",
            "NotebookApp.iopub_data_rate_limit=1000000.0 (bytes/sec)\n",
            "NotebookApp.rate_limit_window=3.0 (secs)\n",
            "\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "ml-latest-small/links.csv    ml-latest-small/README.txt\n",
            "ml-latest-small/movies.csv   ml-latest-small/tags.csv\n",
            "ml-latest-small/ratings.csv\n",
            ".\n",
            "├── ml-latest-small\n",
            "│   ├── links.csv\n",
            "│   ├── movies.csv\n",
            "│   ├── ratings.csv\n",
            "│   ├── README.txt\n",
            "│   └── tags.csv\n",
            "└── sample_data\n",
            "    ├── anscombe.json\n",
            "    ├── california_housing_test.csv\n",
            "    ├── california_housing_train.csv\n",
            "    ├── mnist_test.csv\n",
            "    ├── mnist_train_small.csv\n",
            "    └── README.md\n",
            "\n",
            "2 directories, 11 files\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "TxCBjahfH8JG"
      },
      "source": [
        "### 外部データの利用方法\n",
        "上記ではGoogle Colab実行時に自動で用意される環境内にデータをダウンロードしている。これ以外にもローカルPCのファイルをアップロードしたり、Googleドライブを利用する方法もある。ここでは参考サイトの紹介にとどめる。いろいろ試して好みの方法を利用しよう。\n",
        "- [外部データ: ローカル ファイル、ドライブ、スプレッドシート、Cloud Storage](https://colab.research.google.com/notebooks/io.ipynb?hl=ja)\n",
        "- [Google Colaboratoryでのファイル読み込み方法](https://www.ushiji.online/colab-file-upload)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "bwL94zLI8XSw"
      },
      "source": [
        "### CSVファイルをpd.DataFrameに変換し覗いてみる\n",
        "pandasではデータセットを[DataFrame型](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html)と呼ばれる二次元表形式の構造でデータを管理し、処理することが多い。\n",
        "\n",
        "表をExcelのような表計算ソフトで処理する場合には「行方向インデックス（1〜N）」「列方向インデックス（A〜AZ,,,）」を用いて対象セルを指定し、平均値や分散を求めたり、特定条件に合致する値を抽出して処理することになる。\n",
        "\n",
        "ここでは代表的な行・列指定方法、値の参照方法を眺めていこう。\n",
        "\n",
        "- 参考: ml-latest-small詳細: [ml-latest-small-README.html](http://files.grouplens.org/datasets/movielens/ml-latest-small-README.html)\n",
        "- tips\n",
        "  - ``pd.reac_csv('filename')`` でCSVやTSV形式のファイルを読み込むことができる。なおファイル冒頭に列名が記載されている場合にはそれを列名として読み取ることもできるし、逆にそれをスキップすることもできる。詳細は[ドキュメント](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html)で確認しよう。\n",
        "  - DataFrameに対して ``head()`` で冒頭5個までのデータを眺めることができる。大規模データを全出力しても意味がないため、ざっくりと確認したい場合に便利。\n",
        "  - 今回のデータセットは以下の4つのデータフレームで構成されている。これらを組み合わせて利用すると、例えば「movieId==1は'Toy Story (1995)'で、そのカテゴリは Adventure等複数が付与されている。より詳細情報は[imdbで114709](https://www.imdb.com/title/tt0114709/)から参照できる。この映画に対してuserId==1は4点を付けている」といったことを読み出すことができる。たかだか4つのファイルでも頭の中で組み合わせて考えるのは難しいので、自分なりに図を書いてどう関連しているかを鳥瞰しやすくしよう。\n",
        "\t- links: movieId, imdbId, tmdbId\n",
        "\t- movies: movieId, title, genres\n",
        "\t- ratings: userId, movieId, rating, timestamp\n",
        "\t- tags: userId, movieId, tag, timestamp"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 221
        },
        "id": "NuIkiodo73ia",
        "outputId": "e6b3c3a4-f84a-40fd-f87b-c7c5572ccbc8"
      },
      "source": [
        "links = pd.read_csv('ml-latest-small/links.csv')\n",
        "print(type(links))\n",
        "links.head()"
      ],
      "execution_count": 3,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "<class 'pandas.core.frame.DataFrame'>\n"
          ]
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "\n",
              "  <div id=\"df-7626e3d7-9d93-411f-a4b5-2ef4c2953ad2\">\n",
              "    <div class=\"colab-df-container\">\n",
              "      <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>movieId</th>\n",
              "      <th>imdbId</th>\n",
              "      <th>tmdbId</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>1</td>\n",
              "      <td>114709</td>\n",
              "      <td>862.0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>2</td>\n",
              "      <td>113497</td>\n",
              "      <td>8844.0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>3</td>\n",
              "      <td>113228</td>\n",
              "      <td>15602.0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>4</td>\n",
              "      <td>114885</td>\n",
              "      <td>31357.0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>5</td>\n",
              "      <td>113041</td>\n",
              "      <td>11862.0</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-7626e3d7-9d93-411f-a4b5-2ef4c2953ad2')\"\n",
              "              title=\"Convert this dataframe to an interactive table.\"\n",
              "              style=\"display:none;\">\n",
              "        \n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\">\n",
              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
              "  </svg>\n",
              "      </button>\n",
              "      \n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      flex-wrap:wrap;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "      <script>\n",
              "        const buttonEl =\n",
              "          document.querySelector('#df-7626e3d7-9d93-411f-a4b5-2ef4c2953ad2 button.colab-df-convert');\n",
              "        buttonEl.style.display =\n",
              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "        async function convertToInteractive(key) {\n",
              "          const element = document.querySelector('#df-7626e3d7-9d93-411f-a4b5-2ef4c2953ad2');\n",
              "          const dataTable =\n",
              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                     [key], {});\n",
              "          if (!dataTable) return;\n",
              "\n",
              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "            + ' to learn more about interactive tables.';\n",
              "          element.innerHTML = '';\n",
              "          dataTable['output_type'] = 'display_data';\n",
              "          await google.colab.output.renderOutput(dataTable, element);\n",
              "          const docLink = document.createElement('div');\n",
              "          docLink.innerHTML = docLinkHtml;\n",
              "          element.appendChild(docLink);\n",
              "        }\n",
              "      </script>\n",
              "    </div>\n",
              "  </div>\n",
              "  "
            ],
            "text/plain": [
              "   movieId  imdbId   tmdbId\n",
              "0        1  114709    862.0\n",
              "1        2  113497   8844.0\n",
              "2        3  113228  15602.0\n",
              "3        4  114885  31357.0\n",
              "4        5  113041  11862.0"
            ]
          },
          "metadata": {},
          "execution_count": 3
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 248
        },
        "id": "RXJ1c5ed73pu",
        "outputId": "7bf2ed06-e261-42c2-d4a9-4d345c7ae5d4"
      },
      "source": [
        "movies = pd.read_csv('ml-latest-small/movies.csv')\n",
        "movies.head()"
      ],
      "execution_count": 4,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "\n",
              "  <div id=\"df-bfadcd9b-fa87-4864-a3e3-49c06b49e25d\">\n",
              "    <div class=\"colab-df-container\">\n",
              "      <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>movieId</th>\n",
              "      <th>title</th>\n",
              "      <th>genres</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>1</td>\n",
              "      <td>Toy Story (1995)</td>\n",
              "      <td>Adventure|Animation|Children|Comedy|Fantasy</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>2</td>\n",
              "      <td>Jumanji (1995)</td>\n",
              "      <td>Adventure|Children|Fantasy</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>3</td>\n",
              "      <td>Grumpier Old Men (1995)</td>\n",
              "      <td>Comedy|Romance</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>4</td>\n",
              "      <td>Waiting to Exhale (1995)</td>\n",
              "      <td>Comedy|Drama|Romance</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>5</td>\n",
              "      <td>Father of the Bride Part II (1995)</td>\n",
              "      <td>Comedy</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-bfadcd9b-fa87-4864-a3e3-49c06b49e25d')\"\n",
              "              title=\"Convert this dataframe to an interactive table.\"\n",
              "              style=\"display:none;\">\n",
              "        \n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\">\n",
              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
              "  </svg>\n",
              "      </button>\n",
              "      \n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      flex-wrap:wrap;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "      <script>\n",
              "        const buttonEl =\n",
              "          document.querySelector('#df-bfadcd9b-fa87-4864-a3e3-49c06b49e25d button.colab-df-convert');\n",
              "        buttonEl.style.display =\n",
              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "        async function convertToInteractive(key) {\n",
              "          const element = document.querySelector('#df-bfadcd9b-fa87-4864-a3e3-49c06b49e25d');\n",
              "          const dataTable =\n",
              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                     [key], {});\n",
              "          if (!dataTable) return;\n",
              "\n",
              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "            + ' to learn more about interactive tables.';\n",
              "          element.innerHTML = '';\n",
              "          dataTable['output_type'] = 'display_data';\n",
              "          await google.colab.output.renderOutput(dataTable, element);\n",
              "          const docLink = document.createElement('div');\n",
              "          docLink.innerHTML = docLinkHtml;\n",
              "          element.appendChild(docLink);\n",
              "        }\n",
              "      </script>\n",
              "    </div>\n",
              "  </div>\n",
              "  "
            ],
            "text/plain": [
              "   movieId                               title  \\\n",
              "0        1                    Toy Story (1995)   \n",
              "1        2                      Jumanji (1995)   \n",
              "2        3             Grumpier Old Men (1995)   \n",
              "3        4            Waiting to Exhale (1995)   \n",
              "4        5  Father of the Bride Part II (1995)   \n",
              "\n",
              "                                        genres  \n",
              "0  Adventure|Animation|Children|Comedy|Fantasy  \n",
              "1                   Adventure|Children|Fantasy  \n",
              "2                               Comedy|Romance  \n",
              "3                         Comedy|Drama|Romance  \n",
              "4                                       Comedy  "
            ]
          },
          "metadata": {},
          "execution_count": 4
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 204
        },
        "id": "GXz28hLx8mhm",
        "outputId": "4b560c58-8962-4a1d-8ce2-0c4b11dc55a8"
      },
      "source": [
        "ratings = pd.read_csv('ml-latest-small/ratings.csv')\n",
        "ratings.head()"
      ],
      "execution_count": 5,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "\n",
              "  <div id=\"df-ccde0db9-dddb-4b92-af87-40150ffeae9d\">\n",
              "    <div class=\"colab-df-container\">\n",
              "      <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>userId</th>\n",
              "      <th>movieId</th>\n",
              "      <th>rating</th>\n",
              "      <th>timestamp</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>1</td>\n",
              "      <td>1</td>\n",
              "      <td>4.0</td>\n",
              "      <td>964982703</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>1</td>\n",
              "      <td>3</td>\n",
              "      <td>4.0</td>\n",
              "      <td>964981247</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>1</td>\n",
              "      <td>6</td>\n",
              "      <td>4.0</td>\n",
              "      <td>964982224</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>1</td>\n",
              "      <td>47</td>\n",
              "      <td>5.0</td>\n",
              "      <td>964983815</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>1</td>\n",
              "      <td>50</td>\n",
              "      <td>5.0</td>\n",
              "      <td>964982931</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-ccde0db9-dddb-4b92-af87-40150ffeae9d')\"\n",
              "              title=\"Convert this dataframe to an interactive table.\"\n",
              "              style=\"display:none;\">\n",
              "        \n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\">\n",
              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
              "  </svg>\n",
              "      </button>\n",
              "      \n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      flex-wrap:wrap;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "      <script>\n",
              "        const buttonEl =\n",
              "          document.querySelector('#df-ccde0db9-dddb-4b92-af87-40150ffeae9d button.colab-df-convert');\n",
              "        buttonEl.style.display =\n",
              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "        async function convertToInteractive(key) {\n",
              "          const element = document.querySelector('#df-ccde0db9-dddb-4b92-af87-40150ffeae9d');\n",
              "          const dataTable =\n",
              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                     [key], {});\n",
              "          if (!dataTable) return;\n",
              "\n",
              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "            + ' to learn more about interactive tables.';\n",
              "          element.innerHTML = '';\n",
              "          dataTable['output_type'] = 'display_data';\n",
              "          await google.colab.output.renderOutput(dataTable, element);\n",
              "          const docLink = document.createElement('div');\n",
              "          docLink.innerHTML = docLinkHtml;\n",
              "          element.appendChild(docLink);\n",
              "        }\n",
              "      </script>\n",
              "    </div>\n",
              "  </div>\n",
              "  "
            ],
            "text/plain": [
              "   userId  movieId  rating  timestamp\n",
              "0       1        1     4.0  964982703\n",
              "1       1        3     4.0  964981247\n",
              "2       1        6     4.0  964982224\n",
              "3       1       47     5.0  964983815\n",
              "4       1       50     5.0  964982931"
            ]
          },
          "metadata": {},
          "execution_count": 5
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 204
        },
        "id": "YIzhzKtY8mkk",
        "outputId": "faa411ab-489a-4814-d532-337562e0f1bf"
      },
      "source": [
        "tags = pd.read_csv('ml-latest-small/tags.csv')\n",
        "tags.head()"
      ],
      "execution_count": 6,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "\n",
              "  <div id=\"df-216015c8-7ccc-4efe-99d6-f741a5e8cc52\">\n",
              "    <div class=\"colab-df-container\">\n",
              "      <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>userId</th>\n",
              "      <th>movieId</th>\n",
              "      <th>tag</th>\n",
              "      <th>timestamp</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>2</td>\n",
              "      <td>60756</td>\n",
              "      <td>funny</td>\n",
              "      <td>1445714994</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>2</td>\n",
              "      <td>60756</td>\n",
              "      <td>Highly quotable</td>\n",
              "      <td>1445714996</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>2</td>\n",
              "      <td>60756</td>\n",
              "      <td>will ferrell</td>\n",
              "      <td>1445714992</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>2</td>\n",
              "      <td>89774</td>\n",
              "      <td>Boxing story</td>\n",
              "      <td>1445715207</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>2</td>\n",
              "      <td>89774</td>\n",
              "      <td>MMA</td>\n",
              "      <td>1445715200</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-216015c8-7ccc-4efe-99d6-f741a5e8cc52')\"\n",
              "              title=\"Convert this dataframe to an interactive table.\"\n",
              "              style=\"display:none;\">\n",
              "        \n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\">\n",
              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
              "  </svg>\n",
              "      </button>\n",
              "      \n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      flex-wrap:wrap;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "      <script>\n",
              "        const buttonEl =\n",
              "          document.querySelector('#df-216015c8-7ccc-4efe-99d6-f741a5e8cc52 button.colab-df-convert');\n",
              "        buttonEl.style.display =\n",
              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "        async function convertToInteractive(key) {\n",
              "          const element = document.querySelector('#df-216015c8-7ccc-4efe-99d6-f741a5e8cc52');\n",
              "          const dataTable =\n",
              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                     [key], {});\n",
              "          if (!dataTable) return;\n",
              "\n",
              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "            + ' to learn more about interactive tables.';\n",
              "          element.innerHTML = '';\n",
              "          dataTable['output_type'] = 'display_data';\n",
              "          await google.colab.output.renderOutput(dataTable, element);\n",
              "          const docLink = document.createElement('div');\n",
              "          docLink.innerHTML = docLinkHtml;\n",
              "          element.appendChild(docLink);\n",
              "        }\n",
              "      </script>\n",
              "    </div>\n",
              "  </div>\n",
              "  "
            ],
            "text/plain": [
              "   userId  movieId              tag   timestamp\n",
              "0       2    60756            funny  1445714994\n",
              "1       2    60756  Highly quotable  1445714996\n",
              "2       2    60756     will ferrell  1445714992\n",
              "3       2    89774     Boxing story  1445715207\n",
              "4       2    89774              MMA  1445715200"
            ]
          },
          "metadata": {},
          "execution_count": 6
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "8FTputq7aL-W"
      },
      "source": [
        "## 行や列を指定した簡易処理"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ImEdAtNbdljg"
      },
      "source": [
        "### 特定の行（サンプル）や列（特徴）を指定して眺めてみる\n",
        "moviesはmovieId, title, genresの3要素で構成されるデータが並んでいる。ここではtitleだけを指定し、かつ、冒頭5番目までのデータを出力指定している。\n",
        "\n",
        "- tips\n",
        "  - DataFrameに対して ``['列名']`` で列を指定できる。\n",
        "  - DataFrameに対して ``[start:end]`` のようにスライス処理（これはPythonのリストに対する処理と同等）を記述することで、連続した複数行を指定できる。startを省略した場合は冒頭から、endを省略した場合は最後までという意味になる。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "lH55J-cWdsWc",
        "outputId": "7ad9aa1b-57ae-4c6f-8197-4704ff04a41a"
      },
      "source": [
        "print(movies.columns)\n",
        "print(movies['title'][:5])"
      ],
      "execution_count": 7,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Index(['movieId', 'title', 'genres'], dtype='object')\n",
            "0                      Toy Story (1995)\n",
            "1                        Jumanji (1995)\n",
            "2               Grumpier Old Men (1995)\n",
            "3              Waiting to Exhale (1995)\n",
            "4    Father of the Bride Part II (1995)\n",
            "Name: title, dtype: object\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "2qXGL0OUfH8-",
        "outputId": "d2145fe5-9f55-4fe6-b2a0-14df404d2638"
      },
      "source": [
        "print(movies.loc[:5])"
      ],
      "execution_count": 8,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "   movieId                               title  \\\n",
            "0        1                    Toy Story (1995)   \n",
            "1        2                      Jumanji (1995)   \n",
            "2        3             Grumpier Old Men (1995)   \n",
            "3        4            Waiting to Exhale (1995)   \n",
            "4        5  Father of the Bride Part II (1995)   \n",
            "5        6                         Heat (1995)   \n",
            "\n",
            "                                        genres  \n",
            "0  Adventure|Animation|Children|Comedy|Fantasy  \n",
            "1                   Adventure|Children|Fantasy  \n",
            "2                               Comedy|Romance  \n",
            "3                         Comedy|Drama|Romance  \n",
            "4                                       Comedy  \n",
            "5                        Action|Crime|Thriller  \n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "Me78zNQ9fPTQ",
        "outputId": "f767cbd6-b523-4c85-d8be-e64a504c0124"
      },
      "source": [
        "# 省略させずに全て表示させるにはオプション設定が必要。\n",
        "# これはnumpyでも同様。\n",
        "pd.set_option('display.max_columns', 10)\n",
        "print(movies.loc[:5])"
      ],
      "execution_count": 9,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "   movieId                               title  \\\n",
            "0        1                    Toy Story (1995)   \n",
            "1        2                      Jumanji (1995)   \n",
            "2        3             Grumpier Old Men (1995)   \n",
            "3        4            Waiting to Exhale (1995)   \n",
            "4        5  Father of the Bride Part II (1995)   \n",
            "5        6                         Heat (1995)   \n",
            "\n",
            "                                        genres  \n",
            "0  Adventure|Animation|Children|Comedy|Fantasy  \n",
            "1                   Adventure|Children|Fantasy  \n",
            "2                               Comedy|Romance  \n",
            "3                         Comedy|Drama|Romance  \n",
            "4                                       Comedy  \n",
            "5                        Action|Crime|Thriller  \n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "pQQmse069Dwv"
      },
      "source": [
        "### 条件を指定して眺めてみる1（userId == 1 のレーティングを確認）"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "D8XmFsgyhfQ-",
        "outputId": "2263ef8a-a44b-4de9-934a-b6312e17a3f2"
      },
      "source": [
        "# 条件式だけではTrue/Falseという判断結果しか出力されない。\n",
        "print(ratings['userId'] == 1)"
      ],
      "execution_count": 10,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "0          True\n",
            "1          True\n",
            "2          True\n",
            "3          True\n",
            "4          True\n",
            "          ...  \n",
            "100831    False\n",
            "100832    False\n",
            "100833    False\n",
            "100834    False\n",
            "100835    False\n",
            "Name: userId, Length: 100836, dtype: bool\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "3VUl0hABhyZH",
        "outputId": "eb6aa4c7-e2e2-461f-eca2-0498fe2bb201"
      },
      "source": [
        "# 判断結果に基づいて合致する行を調べるには、同じDataFrameを参照し直す必要がある。\n",
        "print(ratings[ratings['userId'] == 1])"
      ],
      "execution_count": 11,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "     userId  movieId  rating  timestamp\n",
            "0         1        1     4.0  964982703\n",
            "1         1        3     4.0  964981247\n",
            "2         1        6     4.0  964982224\n",
            "3         1       47     5.0  964983815\n",
            "4         1       50     5.0  964982931\n",
            "..      ...      ...     ...        ...\n",
            "227       1     3744     4.0  964980694\n",
            "228       1     3793     5.0  964981855\n",
            "229       1     3809     4.0  964981220\n",
            "230       1     4006     4.0  964982903\n",
            "231       1     5060     5.0  964984002\n",
            "\n",
            "[232 rows x 4 columns]\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "PlpW_zDCij4S"
      },
      "source": [
        "### 数値情報の概要（出現回数・平均・分散・最小値・最大値・四分位数）を眺めてみる"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "KHA2eMqCmHOi",
        "outputId": "45097fc1-6542-4f12-f282-f6887e1f5619"
      },
      "source": [
        "ratings['rating'].mean()"
      ],
      "execution_count": 12,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "3.501556983616962"
            ]
          },
          "metadata": {},
          "execution_count": 12
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "qGjrNzJ6mUJD",
        "outputId": "a5b6fc86-1b89-40e3-e550-3ef56347d965"
      },
      "source": [
        "ratings['rating'].std()"
      ],
      "execution_count": 13,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "1.0425292390605359"
            ]
          },
          "metadata": {},
          "execution_count": 13
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 297
        },
        "id": "eXRkdgoyitVg",
        "outputId": "705f3563-6a76-4541-f5b6-0276f6a84116"
      },
      "source": [
        "ratings.describe()"
      ],
      "execution_count": 14,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "\n",
              "  <div id=\"df-afd2662c-6820-4406-937a-0e71c108fd44\">\n",
              "    <div class=\"colab-df-container\">\n",
              "      <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>userId</th>\n",
              "      <th>movieId</th>\n",
              "      <th>rating</th>\n",
              "      <th>timestamp</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>count</th>\n",
              "      <td>100836.000000</td>\n",
              "      <td>100836.000000</td>\n",
              "      <td>100836.000000</td>\n",
              "      <td>1.008360e+05</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>mean</th>\n",
              "      <td>326.127564</td>\n",
              "      <td>19435.295718</td>\n",
              "      <td>3.501557</td>\n",
              "      <td>1.205946e+09</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>std</th>\n",
              "      <td>182.618491</td>\n",
              "      <td>35530.987199</td>\n",
              "      <td>1.042529</td>\n",
              "      <td>2.162610e+08</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>min</th>\n",
              "      <td>1.000000</td>\n",
              "      <td>1.000000</td>\n",
              "      <td>0.500000</td>\n",
              "      <td>8.281246e+08</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>25%</th>\n",
              "      <td>177.000000</td>\n",
              "      <td>1199.000000</td>\n",
              "      <td>3.000000</td>\n",
              "      <td>1.019124e+09</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>50%</th>\n",
              "      <td>325.000000</td>\n",
              "      <td>2991.000000</td>\n",
              "      <td>3.500000</td>\n",
              "      <td>1.186087e+09</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>75%</th>\n",
              "      <td>477.000000</td>\n",
              "      <td>8122.000000</td>\n",
              "      <td>4.000000</td>\n",
              "      <td>1.435994e+09</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>max</th>\n",
              "      <td>610.000000</td>\n",
              "      <td>193609.000000</td>\n",
              "      <td>5.000000</td>\n",
              "      <td>1.537799e+09</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-afd2662c-6820-4406-937a-0e71c108fd44')\"\n",
              "              title=\"Convert this dataframe to an interactive table.\"\n",
              "              style=\"display:none;\">\n",
              "        \n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\">\n",
              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
              "  </svg>\n",
              "      </button>\n",
              "      \n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      flex-wrap:wrap;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "      <script>\n",
              "        const buttonEl =\n",
              "          document.querySelector('#df-afd2662c-6820-4406-937a-0e71c108fd44 button.colab-df-convert');\n",
              "        buttonEl.style.display =\n",
              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "        async function convertToInteractive(key) {\n",
              "          const element = document.querySelector('#df-afd2662c-6820-4406-937a-0e71c108fd44');\n",
              "          const dataTable =\n",
              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                     [key], {});\n",
              "          if (!dataTable) return;\n",
              "\n",
              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "            + ' to learn more about interactive tables.';\n",
              "          element.innerHTML = '';\n",
              "          dataTable['output_type'] = 'display_data';\n",
              "          await google.colab.output.renderOutput(dataTable, element);\n",
              "          const docLink = document.createElement('div');\n",
              "          docLink.innerHTML = docLinkHtml;\n",
              "          element.appendChild(docLink);\n",
              "        }\n",
              "      </script>\n",
              "    </div>\n",
              "  </div>\n",
              "  "
            ],
            "text/plain": [
              "              userId        movieId         rating     timestamp\n",
              "count  100836.000000  100836.000000  100836.000000  1.008360e+05\n",
              "mean      326.127564   19435.295718       3.501557  1.205946e+09\n",
              "std       182.618491   35530.987199       1.042529  2.162610e+08\n",
              "min         1.000000       1.000000       0.500000  8.281246e+08\n",
              "25%       177.000000    1199.000000       3.000000  1.019124e+09\n",
              "50%       325.000000    2991.000000       3.500000  1.186087e+09\n",
              "75%       477.000000    8122.000000       4.000000  1.435994e+09\n",
              "max       610.000000  193609.000000       5.000000  1.537799e+09"
            ]
          },
          "metadata": {},
          "execution_count": 14
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 297
        },
        "id": "lmWJmo9f7310",
        "outputId": "b5eed96e-8060-4f4f-bf3b-f7ebeb811a68"
      },
      "source": [
        "# userId == 1の概要\n",
        "df = ratings[ratings['userId'] == 1]\n",
        "df.describe()"
      ],
      "execution_count": 15,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "\n",
              "  <div id=\"df-04a8dbe4-53e9-4483-894a-1c94a648f3c7\">\n",
              "    <div class=\"colab-df-container\">\n",
              "      <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>userId</th>\n",
              "      <th>movieId</th>\n",
              "      <th>rating</th>\n",
              "      <th>timestamp</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>count</th>\n",
              "      <td>232.0</td>\n",
              "      <td>232.000000</td>\n",
              "      <td>232.000000</td>\n",
              "      <td>2.320000e+02</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>mean</th>\n",
              "      <td>1.0</td>\n",
              "      <td>1854.603448</td>\n",
              "      <td>4.366379</td>\n",
              "      <td>9.649856e+08</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>std</th>\n",
              "      <td>0.0</td>\n",
              "      <td>1055.962726</td>\n",
              "      <td>0.800048</td>\n",
              "      <td>4.841309e+04</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>min</th>\n",
              "      <td>1.0</td>\n",
              "      <td>1.000000</td>\n",
              "      <td>1.000000</td>\n",
              "      <td>9.649805e+08</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>25%</th>\n",
              "      <td>1.0</td>\n",
              "      <td>1047.250000</td>\n",
              "      <td>4.000000</td>\n",
              "      <td>9.649817e+08</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>50%</th>\n",
              "      <td>1.0</td>\n",
              "      <td>1960.500000</td>\n",
              "      <td>5.000000</td>\n",
              "      <td>9.649824e+08</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>75%</th>\n",
              "      <td>1.0</td>\n",
              "      <td>2641.750000</td>\n",
              "      <td>5.000000</td>\n",
              "      <td>9.649830e+08</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>max</th>\n",
              "      <td>1.0</td>\n",
              "      <td>5060.000000</td>\n",
              "      <td>5.000000</td>\n",
              "      <td>9.657197e+08</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-04a8dbe4-53e9-4483-894a-1c94a648f3c7')\"\n",
              "              title=\"Convert this dataframe to an interactive table.\"\n",
              "              style=\"display:none;\">\n",
              "        \n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\">\n",
              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
              "  </svg>\n",
              "      </button>\n",
              "      \n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      flex-wrap:wrap;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "      <script>\n",
              "        const buttonEl =\n",
              "          document.querySelector('#df-04a8dbe4-53e9-4483-894a-1c94a648f3c7 button.colab-df-convert');\n",
              "        buttonEl.style.display =\n",
              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "        async function convertToInteractive(key) {\n",
              "          const element = document.querySelector('#df-04a8dbe4-53e9-4483-894a-1c94a648f3c7');\n",
              "          const dataTable =\n",
              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                     [key], {});\n",
              "          if (!dataTable) return;\n",
              "\n",
              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "            + ' to learn more about interactive tables.';\n",
              "          element.innerHTML = '';\n",
              "          dataTable['output_type'] = 'display_data';\n",
              "          await google.colab.output.renderOutput(dataTable, element);\n",
              "          const docLink = document.createElement('div');\n",
              "          docLink.innerHTML = docLinkHtml;\n",
              "          element.appendChild(docLink);\n",
              "        }\n",
              "      </script>\n",
              "    </div>\n",
              "  </div>\n",
              "  "
            ],
            "text/plain": [
              "       userId      movieId      rating     timestamp\n",
              "count   232.0   232.000000  232.000000  2.320000e+02\n",
              "mean      1.0  1854.603448    4.366379  9.649856e+08\n",
              "std       0.0  1055.962726    0.800048  4.841309e+04\n",
              "min       1.0     1.000000    1.000000  9.649805e+08\n",
              "25%       1.0  1047.250000    4.000000  9.649817e+08\n",
              "50%       1.0  1960.500000    5.000000  9.649824e+08\n",
              "75%       1.0  2641.750000    5.000000  9.649830e+08\n",
              "max       1.0  5060.000000    5.000000  9.657197e+08"
            ]
          },
          "metadata": {},
          "execution_count": 15
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 297
        },
        "id": "wlmMzPVgm8OP",
        "outputId": "9bfba7fe-8d6b-4613-a3ab-ee6bc3bc90a3"
      },
      "source": [
        "# レーティングの値は1〜5の整数値。\n",
        "# その平均値や分散に小数点下5桁とかの意味はある？\n",
        "# 必要に応じて出力桁を調整するか、値そのものを調整することがある。\n",
        "# ここでは値はそのままにし、print出力時の表示のみ調整しよう。\n",
        "pd.options.display.precision = 2\n",
        "df.describe()"
      ],
      "execution_count": 16,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "\n",
              "  <div id=\"df-95e36562-8832-4460-bd08-b24f3b00f158\">\n",
              "    <div class=\"colab-df-container\">\n",
              "      <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>userId</th>\n",
              "      <th>movieId</th>\n",
              "      <th>rating</th>\n",
              "      <th>timestamp</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>count</th>\n",
              "      <td>232.0</td>\n",
              "      <td>232.00</td>\n",
              "      <td>232.00</td>\n",
              "      <td>2.32e+02</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>mean</th>\n",
              "      <td>1.0</td>\n",
              "      <td>1854.60</td>\n",
              "      <td>4.37</td>\n",
              "      <td>9.65e+08</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>std</th>\n",
              "      <td>0.0</td>\n",
              "      <td>1055.96</td>\n",
              "      <td>0.80</td>\n",
              "      <td>4.84e+04</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>min</th>\n",
              "      <td>1.0</td>\n",
              "      <td>1.00</td>\n",
              "      <td>1.00</td>\n",
              "      <td>9.65e+08</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>25%</th>\n",
              "      <td>1.0</td>\n",
              "      <td>1047.25</td>\n",
              "      <td>4.00</td>\n",
              "      <td>9.65e+08</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>50%</th>\n",
              "      <td>1.0</td>\n",
              "      <td>1960.50</td>\n",
              "      <td>5.00</td>\n",
              "      <td>9.65e+08</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>75%</th>\n",
              "      <td>1.0</td>\n",
              "      <td>2641.75</td>\n",
              "      <td>5.00</td>\n",
              "      <td>9.65e+08</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>max</th>\n",
              "      <td>1.0</td>\n",
              "      <td>5060.00</td>\n",
              "      <td>5.00</td>\n",
              "      <td>9.66e+08</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-95e36562-8832-4460-bd08-b24f3b00f158')\"\n",
              "              title=\"Convert this dataframe to an interactive table.\"\n",
              "              style=\"display:none;\">\n",
              "        \n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\">\n",
              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
              "  </svg>\n",
              "      </button>\n",
              "      \n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      flex-wrap:wrap;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "      <script>\n",
              "        const buttonEl =\n",
              "          document.querySelector('#df-95e36562-8832-4460-bd08-b24f3b00f158 button.colab-df-convert');\n",
              "        buttonEl.style.display =\n",
              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "        async function convertToInteractive(key) {\n",
              "          const element = document.querySelector('#df-95e36562-8832-4460-bd08-b24f3b00f158');\n",
              "          const dataTable =\n",
              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                     [key], {});\n",
              "          if (!dataTable) return;\n",
              "\n",
              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "            + ' to learn more about interactive tables.';\n",
              "          element.innerHTML = '';\n",
              "          dataTable['output_type'] = 'display_data';\n",
              "          await google.colab.output.renderOutput(dataTable, element);\n",
              "          const docLink = document.createElement('div');\n",
              "          docLink.innerHTML = docLinkHtml;\n",
              "          element.appendChild(docLink);\n",
              "        }\n",
              "      </script>\n",
              "    </div>\n",
              "  </div>\n",
              "  "
            ],
            "text/plain": [
              "       userId  movieId  rating  timestamp\n",
              "count   232.0   232.00  232.00   2.32e+02\n",
              "mean      1.0  1854.60    4.37   9.65e+08\n",
              "std       0.0  1055.96    0.80   4.84e+04\n",
              "min       1.0     1.00    1.00   9.65e+08\n",
              "25%       1.0  1047.25    4.00   9.65e+08\n",
              "50%       1.0  1960.50    5.00   9.65e+08\n",
              "75%       1.0  2641.75    5.00   9.65e+08\n",
              "max       1.0  5060.00    5.00   9.66e+08"
            ]
          },
          "metadata": {},
          "execution_count": 16
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "D9GjnyQ7eJsx"
      },
      "source": [
        "## 大雑把に可視化してみる\n",
        "- tips\n",
        "  - DataFrameに対して[plot](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.plot.html)でグラフ描画できる。ただし全ての数値をプロット対象とするため、必要に応じて指定した方が良い。\n",
        "  - [seaborn](https://seaborn.pydata.org)も便利。ここでは箱ひげ図出力に使っていますが、上記のDataFrame.plotでも箱ひげ図自体は作図できます。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "v39wz6n5hX7k"
      },
      "source": [
        "### pd.plotでグラフ描画"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 293
        },
        "id": "QOJGKwwweO5V",
        "outputId": "417b390e-d7b5-495a-b33d-7340729434b0"
      },
      "source": [
        "# DataFrameに対してplot()を実行すると、\n",
        "# 数値データを全て折れ線グラフで出力する。\n",
        "\n",
        "ratings.plot()"
      ],
      "execution_count": 17,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "<matplotlib.axes._subplots.AxesSubplot at 0x7fc6e15a1a90>"
            ]
          },
          "metadata": {},
          "execution_count": 17
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 282
        },
        "id": "28o-_Wfeem86",
        "outputId": "606b101b-8f15-4ecf-efcf-3581a65fd387"
      },
      "source": [
        "# 集計と同様にカラム指定も可能。\n",
        "\n",
        "ratings['rating'].plot()"
      ],
      "execution_count": 18,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "<matplotlib.axes._subplots.AxesSubplot at 0x7fc6e1018ad0>"
            ]
          },
          "metadata": {},
          "execution_count": 18
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "GhsX_YLphikQ"
      },
      "source": [
        "### 条件絞り込んでpd.plot"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 520
        },
        "id": "xESdFOWxe1x6",
        "outputId": "cd652e15-51b2-49f0-9fba-ebf15b3c9d49"
      },
      "source": [
        "# movieId == 1 だけ抽出\n",
        "\n",
        "temp = ratings[ ratings['movieId']==1 ]\n",
        "print(temp)\n",
        "temp.describe()\n",
        "temp['rating'].plot()"
      ],
      "execution_count": 19,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "       userId  movieId  rating   timestamp\n",
            "0           1        1     4.0   964982703\n",
            "516         5        1     4.0   847434962\n",
            "874         7        1     4.5  1106635946\n",
            "1434       15        1     2.5  1510577970\n",
            "1667       17        1     4.5  1305696483\n",
            "...       ...      ...     ...         ...\n",
            "97364     606        1     2.5  1349082950\n",
            "98479     607        1     4.0   964744033\n",
            "98666     608        1     2.5  1117408267\n",
            "99497     609        1     3.0   847221025\n",
            "99534     610        1     5.0  1479542900\n",
            "\n",
            "[215 rows x 4 columns]\n"
          ]
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "<matplotlib.axes._subplots.AxesSubplot at 0x7fc6e10000d0>"
            ]
          },
          "metadata": {},
          "execution_count": 19
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "V5f6BRyUhp9q"
      },
      "source": [
        "### pd.plot(kind='hist')でヒストグラム"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 282
        },
        "id": "MH63nLYBgdgg",
        "outputId": "f09dab09-3b03-43b2-aaa7-98de2d589fb0"
      },
      "source": [
        "# 折れ線グラフでは良く分からないのでヒストグラムにしてみる。\n",
        "\n",
        "temp['rating'].plot(kind='hist')"
      ],
      "execution_count": 20,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "<matplotlib.axes._subplots.AxesSubplot at 0x7fc6e0f6fad0>"
            ]
          },
          "metadata": {},
          "execution_count": 20
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAAX4AAAD4CAYAAADrRI2NAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAARfUlEQVR4nO3dfcxedX3H8ffHFsKDDzzddh2VFSeBERXEW9SgLoI4FAZscw6npjHE7sFtOpdoNcvURBNINtEtm7MTt/qIiCBMnLNW1Jg48C5UeTQoFm0FevvAEDQi+t0f1+m8295tr5ae67T83q/kynXO71znOt+ePz73r7/rd85JVSFJasejhi5AkjRZBr8kNcbgl6TGGPyS1BiDX5Ias3DoAsZxxBFH1NKlS4cuQ5L2KWvXrv1+VU1t3b5PBP/SpUuZmZkZugxJ2qckuXO+dod6JKkxBr8kNcbgl6TGGPyS1BiDX5IaY/BLUmMMfklqjMEvSY0x+CWpMfvElbuS9h5LV1w92LHXX3DmYMd+JLHHL0mN6TX4k/x1kpuT3JTko0kOSHJ0kmuTfDPJx5Ls32cNkqQt9Rb8SY4E/gqYrqonAwuA84ALgYuq6knAj4Dz+6pBkrStvod6FgIHJlkIHATcBZwKXNZtXwWc23MNkqQ5egv+qtoI/D3wHUaB/7/AWuDeqnqo+9gG4Mj59k+yPMlMkpnZ2dm+ypSk5vQ51HMocA5wNPDrwMHAGePuX1Urq2q6qqanprZ5joAkaTf1OdTzAuDbVTVbVT8HLgdOAQ7phn4AlgAbe6xBkrSVPoP/O8CzkhyUJMBpwC3ANcBLus8sA67ssQZJ0lb6HOO/ltGPuNcDN3bHWgm8EXh9km8ChwMX91WDJGlbvV65W1VvAd6yVfMdwMl9HleStH1euStJjTH4JakxBr8kNcbgl6TGGPyS1BiDX5IaY/BLUmMMfklqjMEvSY0x+CWpMQa/JDXG4Jekxhj8ktQYg1+SGmPwS1JjDH5JakyfD1s/Nsm6Oa/7krwuyWFJVie5vXs/tK8aJEnb6vPRi9+oqhOr6kTg6cBPgCuAFcCaqjoGWNOtS5ImZFJDPacB36qqO4FzgFVd+yrg3AnVIElicsF/HvDRbnlRVd3VLd8NLJpvhyTLk8wkmZmdnZ1EjZLUhN6DP8n+wNnAx7feVlUF1Hz7VdXKqpququmpqameq5Skdkyix/8i4PqquqdbvyfJYoDufdMEapAkdSYR/C/jV8M8AFcBy7rlZcCVE6hBktTpNfiTHAycDlw+p/kC4PQktwMv6NYlSROysM8vr6oHgMO3avsBo1k+kqQBeOWuJDXG4Jekxhj8ktQYg1+SGmPwS1JjDH5JaozBL0mNMfglqTEGvyQ1xuCXpMYY/JLUGINfkhpj8EtSYwx+SWqMwS9JjTH4JakxfT+B65AklyW5LcmtSZ6d5LAkq5Pc3r0f2mcNkqQt9d3jfzfwmao6DjgBuBVYAaypqmOANd26JGlCegv+JI8DngdcDFBVD1bVvcA5wKruY6uAc/uqQZK0rT57/EcDs8C/J7khyfu6h68vqqq7us/cDSyab+cky5PMJJmZnZ3tsUxJakufwb8QOAl4T1U9DXiArYZ1qqqAmm/nqlpZVdNVNT01NdVjmZLUlj6DfwOwoaqu7dYvY/SH4J4kiwG690091iBJ2kpvwV9VdwPfTXJs13QacAtwFbCsa1sGXNlXDZKkbS3s+fv/Evhwkv2BO4BXMfpjc2mS84E7gZf2XIMkaY5eg7+q1gHT82w6rc/jSpK2zyt3JakxBr8kNcbgl6TGGPyS1BiDX5IaY/BLUmMMfklqjMEvSY0x+CWpMQa/JDXG4Jekxhj8ktQYg1+SGmPwS1Jjxgr+JE/puxBJ0mSM2+P/lyTXJfnzJI/rtSJJUq/GCv6qei7wcuAJwNokH0ly+s72S7I+yY1J1iWZ6doOS7I6ye3d+6EP618gSdolY4/xV9XtwN8CbwR+G/jHJLcl+f2d7Pr8qjqxqjY/iWsFsKaqjgHWdOuSpAkZd4z/qUkuAm4FTgV+t6p+q1u+aBePeQ6wqlteBZy7i/tLkh6GcXv8/wRcD5xQVa+pqusBqup7jP4XsD0FfDbJ2iTLu7ZFVXVXt3w3sGg36pYk7aZxH7Z+JvDTqvoFQJJHAQdU1U+q6oM72O85VbUxyeOB1Ulum7uxqipJzbdj94diOcBRRx01ZpmSpJ0Zt8f/OeDAOesHdW07VFUbu/dNwBXAycA9SRYDdO+btrPvyqqarqrpqampMcuUJO3MuMF/QFXdv3mlWz5oRzskOTjJYzYvAy8EbgKuApZ1H1sGXLmrRUuSdt+4Qz0PJDlp89h+kqcDP93JPouAK5JsPs5HquozSb4KXJrkfOBO4KW7V7okaXeMG/yvAz6e5HtAgF8D/mhHO1TVHcAJ87T/ADhtF+uUJO0hYwV/VX01yXHAsV3TN6rq5/2VJUnqy7g9foBnAEu7fU5KQlV9oJeqJEm9GSv4k3wQ+E1gHfCLrrkAg1/SI97SFVcPctz1F5zZy/eO2+OfBo6vqnnn3EuS9h3jTue8idEPupKkfdy4Pf4jgFuSXAf8bHNjVZ3dS1WSpN6MG/xv7bMISdLkjDud84tJfgM4pqo+l+QgYEG/pUmS+jDubZlfDVwGvLdrOhL4ZF9FSZL6M+6Pu68BTgHug/9/KMvj+ypKktSfcYP/Z1X14OaVJAsZzeOXJO1jxg3+LyZ5M3Bg96zdjwP/2V9ZkqS+jBv8K4BZ4EbgT4BPs+Mnb0mS9lLjzur5JfBv3UuStA8b914932aeMf2qeuIer0iS1KtduVfPZgcAfwgctufLkST1bawx/qr6wZzXxqp6F6MHsEuS9jHjDvWcNGf1UYz+BzDuvguAGWBjVZ2V5GjgEuBwYC3wyrlTRSVJ/Rp3qOcf5iw/BKxn/Gflvha4FXhst34hcFFVXZLkX4HzgfeM+V2SpIdp3Fk9z9+dL0+yhNGQ0DuA12f05PVTgT/uPrKK0Q3gDH5JmpBxh2tev6PtVfXO7Wx6F/AG4DHd+uHAvVX1ULe+gdF9f+Y75nJgOcBRRx01TpmSpDGMewHXNPBnjEL6SOBPgZMYBfpj5tshyVnApqpauzuFVdXKqpququmpqand+QpJ0jzGHeNfApxUVT8GSPJW4OqqesUO9jkFODvJixlNAX0s8G7gkCQLu17/EmDj7hYvSdp14/b4FwFzZ9482LVtV1W9qaqWVNVS4Dzg81X1cuAa4CXdx5YBV+5SxZKkh2XcHv8HgOuSXNGtn8voh9nd8UbgkiRvB24ALt7N75Ek7YZxZ/W8I8l/Ac/tml5VVTeMe5Cq+gLwhW75DuDkXStTkrSnjDvUA3AQcF9VvRvY0F2IJUnax4z76MW3MBqieVPXtB/wob6KkiT1Z9we/+8BZwMPAFTV99jONE5J0t5t3OB/sKqK7tbMSQ7uryRJUp/GDf5Lk7yX0Rz8VwOfw4eySNI+aaezerr763wMOA64DzgW+LuqWt1zbZKkHuw0+Kuqkny6qp4CGPaStI8bd6jn+iTP6LUSSdJEjHvl7jOBVyRZz2hmTxj9Z+CpfRUmSerHDoM/yVFV9R3gdyZUj7RPWbri6sGOvf4Cn36q3bOzHv8nGd2V884kn6iqP5hEUZKk/uxsjD9zlp/YZyGSpMnYWfDXdpYlSfuonQ31nJDkPkY9/wO7ZfjVj7uP3f6ukqS90Q6Dv6oWTKoQSdJk7MptmSVJjwC9BX+SA5Jcl+RrSW5O8rau/egk1yb5ZpKPJdm/rxokSdvqs8f/M+DUqjoBOBE4I8mzgAuBi6rqScCPgPN7rEGStJXegr9G7u9W9+teBZwKXNa1r2L0/F5J0oT0OsafZEGSdcAmRjd4+xZwb1U91H1kA3DkdvZdnmQmyczs7GyfZUpSU3oN/qr6RVWdCCxh9ID143Zh35VVNV1V01NTU73VKEmtmcisnqq6F7gGeDajh7lsnka6BNg4iRokSSN9zuqZSnJIt3wgcDpwK6M/AC/pPrYMuLKvGiRJ2xr3tsy7YzGwKskCRn9gLq2qTyW5BbgkyduBG4CLe6xBkrSV3oK/qr4OPG2e9jsYjfdLkgbglbuS1BiDX5IaY/BLUmMMfklqjMEvSY0x+CWpMQa/JDXG4Jekxhj8ktQYg1+SGmPwS1JjDH5JaozBL0mNMfglqTEGvyQ1xuCXpMb0+ejFJyS5JsktSW5O8tqu/bAkq5Pc3r0f2lcNkqRt9dnjfwj4m6o6HngW8JokxwMrgDVVdQywpluXJE1Ib8FfVXdV1fXd8o8ZPWj9SOAcYFX3sVXAuX3VIEna1kTG+JMsZfT83WuBRVV1V7fpbmDRdvZZnmQmyczs7OwkypSkJvQe/EkeDXwCeF1V3Td3W1UVUPPtV1Urq2q6qqanpqb6LlOSmtFr8CfZj1Hof7iqLu+a70myuNu+GNjUZw2SpC31OasnwMXArVX1zjmbrgKWdcvLgCv7qkGStK2FPX73KcArgRuTrOva3gxcAFya5HzgTuClPdYgSdpKb8FfVV8Gsp3Np/V1XKkVS1dcPXQJE9fiv7kPXrkrSY0x+CWpMQa/JDXG4Jekxhj8ktQYg1+SGmPwS1JjDH5JaozBL0mNMfglqTEGvyQ1xuCXpMYY/JLUGINfkhpj8EtSYwx+SWpMn49efH+STUlumtN2WJLVSW7v3g/t6/iSpPn12eP/D+CMrdpWAGuq6hhgTbcuSZqg3oK/qr4E/HCr5nOAVd3yKuDcvo4vSZrfpMf4F1XVXd3y3cCiCR9fkpo32I+7VVVAbW97kuVJZpLMzM7OTrAySXpkm3Tw35NkMUD3vml7H6yqlVU1XVXTU1NTEytQkh7pJh38VwHLuuVlwJUTPr4kNa/P6ZwfBb4CHJtkQ5LzgQuA05PcDrygW5ckTdDCvr64ql62nU2n9XVMSdLO9Rb80iQtXXH10CVI+wxv2SBJjTH4JakxBr8kNcbgl6TG+OOu9hh/YJX2Dfb4JakxBr8kNcbgl6TGGPyS1BiDX5IaY/BLUmMMfklqjMEvSY0x+CWpMQa/JDXG4Jekxgxyr54kZwDvBhYA76uq3h7BONT9Y9ZfcOYgxwXvmSNpxybe40+yAPhn4EXA8cDLkhw/6TokqVVDDPWcDHyzqu6oqgeBS4BzBqhDkpo0xFDPkcB356xvAJ659YeSLAeWd6v3J/nGBGrbY3LhNk1HAN+ffCV7Jc/FljwfW/J8dHLhwz4XvzFf4157P/6qWgmsHLqOPSXJTFVND13H3sBzsSXPx5Y8H7/S17kYYqhnI/CEOetLujZJ0gQMEfxfBY5JcnSS/YHzgKsGqEOSmjTxoZ6qeijJXwD/zWg65/ur6uZJ1zGAR8yw1R7gudiS52NLno9f6eVcpKr6+F5J0l7KK3clqTEGvyQ1xuDvWZL3J9mU5KahaxlakickuSbJLUluTvLaoWsaUpIDklyX5Gvd+Xjb0DUNLcmCJDck+dTQtQwtyfokNyZZl2Rmj363Y/z9SvI84H7gA1X15KHrGVKSxcDiqro+yWOAtcC5VXXLwKUNIkmAg6vq/iT7AV8GXltV/zNwaYNJ8npgGnhsVZ01dD1DSrIemK6qPX4xmz3+nlXVl4AfDl3H3qCq7qqq67vlHwO3MrqSu0k1cn+3ul/3arYnlmQJcCbwvqFreaQz+DWIJEuBpwHXDlvJsLqhjXXAJmB1VbV8Pt4FvAH45dCF7CUK+GyStd0tbPYYg18Tl+TRwCeA11XVfUPXM6Sq+kVVncjoCvaTkzQ5HJjkLGBTVa0dupa9yHOq6iRGdzJ+TTdsvEcY/Jqobiz7E8CHq+ryoevZW1TVvcA1wBlD1zKQU4Czu3HtS4BTk3xo2JKGVVUbu/dNwBWM7my8Rxj8mpjux8yLgVur6p1D1zO0JFNJDumWDwROB24btqphVNWbqmpJVS1ldBuXz1fVKwYuazBJDu4mQJDkYOCFwB6bGWjw9yzJR4GvAMcm2ZDk/KFrGtApwCsZ9ebWda8XD13UgBYD1yT5OqN7WK2uquanMQqARcCXk3wNuA64uqo+s6e+3OmcktQYe/yS1BiDX5IaY/BLUmMMfklqjMEvSY0x+CWpMQa/JDXm/wBTSJGrdpHw/AAAAABJRU5ErkJggg==\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "1dIh9yYWhwwd"
      },
      "source": [
        "### seaborn.boxplot で箱ひげ図"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 296
        },
        "id": "G9g0EFoG36XK",
        "outputId": "915968a3-aaca-4a9a-9224-b7c9d45f473a"
      },
      "source": [
        "# 映画毎の箱ひげ図を出力してみる。\n",
        "# 全ての映画を出力すると圧縮されすぎて目視できないため、ここではmovieId=1〜20までを指定。\n",
        "\n",
        "temp = ratings[ratings['movieId'] <= 20]\n",
        "sns.boxplot(x='movieId', y='rating', data=temp)"
      ],
      "execution_count": 21,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "<matplotlib.axes._subplots.AxesSubplot at 0x7fc6e0ff3250>"
            ]
          },
          "metadata": {},
          "execution_count": 21
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "needs_background": "light"
          }
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "KlcblO6Xt0Fc"
      },
      "source": [
        "## テーブルを組み合わせてみる\n",
        "ユーザを行、列を映画とする行列を作成し、各要素の値をratingとする（ない場合にはNoneにする）。これをユーザ・映画行列と呼ぶことにしよう。ユーザ・映画行列を用意できれば「同じ映画集合に対して高評価を付けているユーザグループ」を抽出できるかもしれない。そのようなグループを抽出できたならば「同じグループが高評価しているが、まだ評価されていない映画」を発見することで高評価を得やすい映画を推薦できるだろう。このように映画の視聴履歴を元に推薦する方法を[協調フィルタリング](https://www.ai-gakkai.or.jp/whatsai/AItopics2.html)と呼ぶ。\n",
        "\n",
        "今は詳細を省くが、以下の手順で視聴履歴を利用してみよう。\n",
        "\n",
        "- step 1: ユーザ・映画行列を作成。\n",
        "- step 2: ユーザ間の類似度を算出。\n",
        "- step 3: あるユーザiに対する最大類似度となるユーザjを抽出。\n",
        "- step 4: ユーザjが高く評価している映画をリストアップ。\n",
        "- step 5: リストアップした映画からユーザiが見ていないもの（＝推薦候補）を抽出。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "YvzNdw6yy0sx"
      },
      "source": [
        "### step 1: ユーザ・映画行列を作成。\n",
        "- ``NaN`` は Not a Number の略。数値ではない値のこと。ここでは該当要素に値がなかった場合のデフォルト値として設定されている。\n",
        "- [pd.pivot_table](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.pivot_table.html)でピボットテーブルを作成。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 514
        },
        "id": "pOigiJ1ct177",
        "outputId": "ec45f077-e7b9-4445-fbf9-60c9a491088f"
      },
      "source": [
        "df = ratings.pivot_table(index='userId', columns='movieId', values='rating')\n",
        "df"
      ],
      "execution_count": 22,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "\n",
              "  <div id=\"df-bb502afe-66f2-4bc4-8c1e-1b24af1a0f04\">\n",
              "    <div class=\"colab-df-container\">\n",
              "      <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>movieId</th>\n",
              "      <th>1</th>\n",
              "      <th>2</th>\n",
              "      <th>3</th>\n",
              "      <th>4</th>\n",
              "      <th>5</th>\n",
              "      <th>...</th>\n",
              "      <th>193581</th>\n",
              "      <th>193583</th>\n",
              "      <th>193585</th>\n",
              "      <th>193587</th>\n",
              "      <th>193609</th>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>userId</th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "      <th></th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>4.0</td>\n",
              "      <td>NaN</td>\n",
              "      <td>4.0</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>...</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>...</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>...</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>...</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>5</th>\n",
              "      <td>4.0</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>...</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>...</th>\n",
              "      <td>...</td>\n",
              "      <td>...</td>\n",
              "      <td>...</td>\n",
              "      <td>...</td>\n",
              "      <td>...</td>\n",
              "      <td>...</td>\n",
              "      <td>...</td>\n",
              "      <td>...</td>\n",
              "      <td>...</td>\n",
              "      <td>...</td>\n",
              "      <td>...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>606</th>\n",
              "      <td>2.5</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>...</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>607</th>\n",
              "      <td>4.0</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>...</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>608</th>\n",
              "      <td>2.5</td>\n",
              "      <td>2.0</td>\n",
              "      <td>2.0</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>...</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>609</th>\n",
              "      <td>3.0</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>...</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>610</th>\n",
              "      <td>5.0</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>...</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "<p>610 rows × 9724 columns</p>\n",
              "</div>\n",
              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-bb502afe-66f2-4bc4-8c1e-1b24af1a0f04')\"\n",
              "              title=\"Convert this dataframe to an interactive table.\"\n",
              "              style=\"display:none;\">\n",
              "        \n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\">\n",
              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
              "  </svg>\n",
              "      </button>\n",
              "      \n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      flex-wrap:wrap;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "      <script>\n",
              "        const buttonEl =\n",
              "          document.querySelector('#df-bb502afe-66f2-4bc4-8c1e-1b24af1a0f04 button.colab-df-convert');\n",
              "        buttonEl.style.display =\n",
              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "        async function convertToInteractive(key) {\n",
              "          const element = document.querySelector('#df-bb502afe-66f2-4bc4-8c1e-1b24af1a0f04');\n",
              "          const dataTable =\n",
              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                     [key], {});\n",
              "          if (!dataTable) return;\n",
              "\n",
              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "            + ' to learn more about interactive tables.';\n",
              "          element.innerHTML = '';\n",
              "          dataTable['output_type'] = 'display_data';\n",
              "          await google.colab.output.renderOutput(dataTable, element);\n",
              "          const docLink = document.createElement('div');\n",
              "          docLink.innerHTML = docLinkHtml;\n",
              "          element.appendChild(docLink);\n",
              "        }\n",
              "      </script>\n",
              "    </div>\n",
              "  </div>\n",
              "  "
            ],
            "text/plain": [
              "movieId  1       2       3       4       5       ...  193581  193583  193585  \\\n",
              "userId                                           ...                           \n",
              "1           4.0     NaN     4.0     NaN     NaN  ...     NaN     NaN     NaN   \n",
              "2           NaN     NaN     NaN     NaN     NaN  ...     NaN     NaN     NaN   \n",
              "3           NaN     NaN     NaN     NaN     NaN  ...     NaN     NaN     NaN   \n",
              "4           NaN     NaN     NaN     NaN     NaN  ...     NaN     NaN     NaN   \n",
              "5           4.0     NaN     NaN     NaN     NaN  ...     NaN     NaN     NaN   \n",
              "...         ...     ...     ...     ...     ...  ...     ...     ...     ...   \n",
              "606         2.5     NaN     NaN     NaN     NaN  ...     NaN     NaN     NaN   \n",
              "607         4.0     NaN     NaN     NaN     NaN  ...     NaN     NaN     NaN   \n",
              "608         2.5     2.0     2.0     NaN     NaN  ...     NaN     NaN     NaN   \n",
              "609         3.0     NaN     NaN     NaN     NaN  ...     NaN     NaN     NaN   \n",
              "610         5.0     NaN     NaN     NaN     NaN  ...     NaN     NaN     NaN   \n",
              "\n",
              "movieId  193587  193609  \n",
              "userId                   \n",
              "1           NaN     NaN  \n",
              "2           NaN     NaN  \n",
              "3           NaN     NaN  \n",
              "4           NaN     NaN  \n",
              "5           NaN     NaN  \n",
              "...         ...     ...  \n",
              "606         NaN     NaN  \n",
              "607         NaN     NaN  \n",
              "608         NaN     NaN  \n",
              "609         NaN     NaN  \n",
              "610         NaN     NaN  \n",
              "\n",
              "[610 rows x 9724 columns]"
            ]
          },
          "metadata": {},
          "execution_count": 22
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "lN5t2sBrIUea",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 390
        },
        "outputId": "22ac9f3f-3ce5-4a0b-9cf3-001eb5eca126"
      },
      "source": [
        "df.describe()"
      ],
      "execution_count": 23,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "\n",
              "  <div id=\"df-34bd272f-0174-4e31-9c0a-b298084d42ab\">\n",
              "    <div class=\"colab-df-container\">\n",
              "      <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>movieId</th>\n",
              "      <th>1</th>\n",
              "      <th>2</th>\n",
              "      <th>3</th>\n",
              "      <th>4</th>\n",
              "      <th>5</th>\n",
              "      <th>...</th>\n",
              "      <th>193581</th>\n",
              "      <th>193583</th>\n",
              "      <th>193585</th>\n",
              "      <th>193587</th>\n",
              "      <th>193609</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>count</th>\n",
              "      <td>215.00</td>\n",
              "      <td>110.00</td>\n",
              "      <td>52.00</td>\n",
              "      <td>7.00</td>\n",
              "      <td>49.00</td>\n",
              "      <td>...</td>\n",
              "      <td>1.0</td>\n",
              "      <td>1.0</td>\n",
              "      <td>1.0</td>\n",
              "      <td>1.0</td>\n",
              "      <td>1.0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>mean</th>\n",
              "      <td>3.92</td>\n",
              "      <td>3.43</td>\n",
              "      <td>3.26</td>\n",
              "      <td>2.36</td>\n",
              "      <td>3.07</td>\n",
              "      <td>...</td>\n",
              "      <td>4.0</td>\n",
              "      <td>3.5</td>\n",
              "      <td>3.5</td>\n",
              "      <td>3.5</td>\n",
              "      <td>4.0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>std</th>\n",
              "      <td>0.83</td>\n",
              "      <td>0.88</td>\n",
              "      <td>1.05</td>\n",
              "      <td>0.85</td>\n",
              "      <td>0.91</td>\n",
              "      <td>...</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "      <td>NaN</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>min</th>\n",
              "      <td>0.50</td>\n",
              "      <td>0.50</td>\n",
              "      <td>0.50</td>\n",
              "      <td>1.00</td>\n",
              "      <td>0.50</td>\n",
              "      <td>...</td>\n",
              "      <td>4.0</td>\n",
              "      <td>3.5</td>\n",
              "      <td>3.5</td>\n",
              "      <td>3.5</td>\n",
              "      <td>4.0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>25%</th>\n",
              "      <td>3.50</td>\n",
              "      <td>3.00</td>\n",
              "      <td>3.00</td>\n",
              "      <td>1.75</td>\n",
              "      <td>3.00</td>\n",
              "      <td>...</td>\n",
              "      <td>4.0</td>\n",
              "      <td>3.5</td>\n",
              "      <td>3.5</td>\n",
              "      <td>3.5</td>\n",
              "      <td>4.0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>50%</th>\n",
              "      <td>4.00</td>\n",
              "      <td>3.50</td>\n",
              "      <td>3.00</td>\n",
              "      <td>3.00</td>\n",
              "      <td>3.00</td>\n",
              "      <td>...</td>\n",
              "      <td>4.0</td>\n",
              "      <td>3.5</td>\n",
              "      <td>3.5</td>\n",
              "      <td>3.5</td>\n",
              "      <td>4.0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>75%</th>\n",
              "      <td>4.50</td>\n",
              "      <td>4.00</td>\n",
              "      <td>4.00</td>\n",
              "      <td>3.00</td>\n",
              "      <td>3.50</td>\n",
              "      <td>...</td>\n",
              "      <td>4.0</td>\n",
              "      <td>3.5</td>\n",
              "      <td>3.5</td>\n",
              "      <td>3.5</td>\n",
              "      <td>4.0</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>max</th>\n",
              "      <td>5.00</td>\n",
              "      <td>5.00</td>\n",
              "      <td>5.00</td>\n",
              "      <td>3.00</td>\n",
              "      <td>5.00</td>\n",
              "      <td>...</td>\n",
              "      <td>4.0</td>\n",
              "      <td>3.5</td>\n",
              "      <td>3.5</td>\n",
              "      <td>3.5</td>\n",
              "      <td>4.0</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "<p>8 rows × 9724 columns</p>\n",
              "</div>\n",
              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-34bd272f-0174-4e31-9c0a-b298084d42ab')\"\n",
              "              title=\"Convert this dataframe to an interactive table.\"\n",
              "              style=\"display:none;\">\n",
              "        \n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\">\n",
              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
              "  </svg>\n",
              "      </button>\n",
              "      \n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      flex-wrap:wrap;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "      <script>\n",
              "        const buttonEl =\n",
              "          document.querySelector('#df-34bd272f-0174-4e31-9c0a-b298084d42ab button.colab-df-convert');\n",
              "        buttonEl.style.display =\n",
              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "        async function convertToInteractive(key) {\n",
              "          const element = document.querySelector('#df-34bd272f-0174-4e31-9c0a-b298084d42ab');\n",
              "          const dataTable =\n",
              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                     [key], {});\n",
              "          if (!dataTable) return;\n",
              "\n",
              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "            + ' to learn more about interactive tables.';\n",
              "          element.innerHTML = '';\n",
              "          dataTable['output_type'] = 'display_data';\n",
              "          await google.colab.output.renderOutput(dataTable, element);\n",
              "          const docLink = document.createElement('div');\n",
              "          docLink.innerHTML = docLinkHtml;\n",
              "          element.appendChild(docLink);\n",
              "        }\n",
              "      </script>\n",
              "    </div>\n",
              "  </div>\n",
              "  "
            ],
            "text/plain": [
              "movieId  1       2       3       4       5       ...  193581  193583  193585  \\\n",
              "count    215.00  110.00   52.00    7.00   49.00  ...     1.0     1.0     1.0   \n",
              "mean       3.92    3.43    3.26    2.36    3.07  ...     4.0     3.5     3.5   \n",
              "std        0.83    0.88    1.05    0.85    0.91  ...     NaN     NaN     NaN   \n",
              "min        0.50    0.50    0.50    1.00    0.50  ...     4.0     3.5     3.5   \n",
              "25%        3.50    3.00    3.00    1.75    3.00  ...     4.0     3.5     3.5   \n",
              "50%        4.00    3.50    3.00    3.00    3.00  ...     4.0     3.5     3.5   \n",
              "75%        4.50    4.00    4.00    3.00    3.50  ...     4.0     3.5     3.5   \n",
              "max        5.00    5.00    5.00    3.00    5.00  ...     4.0     3.5     3.5   \n",
              "\n",
              "movieId  193587  193609  \n",
              "count       1.0     1.0  \n",
              "mean        3.5     4.0  \n",
              "std         NaN     NaN  \n",
              "min         3.5     4.0  \n",
              "25%         3.5     4.0  \n",
              "50%         3.5     4.0  \n",
              "75%         3.5     4.0  \n",
              "max         3.5     4.0  \n",
              "\n",
              "[8 rows x 9724 columns]"
            ]
          },
          "metadata": {},
          "execution_count": 23
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "UTthDQ6s2u9K"
      },
      "source": [
        "### step 2: ユーザ間の類似度を算出。\n",
        "ユーザ間類似度は「評価値の二乗誤差」を用いることにしよう。同じ映画を見ているとは限らないため、視聴映画リストで重複している映画だけを抽出し、誤差を算出する必要がある。\n",
        "- [df.notnull](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.notnull.html)で欠損値を除外。\n",
        "- [df.index](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.index.html)で該当列インデックスを参照。\n",
        "- [set.intersection](https://docs.python.org/ja/3/library/stdtypes.html#frozenset.intersection)で共通集合を抽出。\n",
        "- [np.array](https://numpy.org/doc/stable/reference/generated/numpy.array.html)でnumpy用配列（ndarray）型に変換。\n",
        "- [np.dot](https://numpy.org/doc/stable/reference/generated/numpy.dot.html)で内積計算。\n",
        "- [np.linalg.norm](https://numpy.org/doc/stable/reference/generated/numpy.linalg.norm.html#numpy.linalg.norm)でベクトルのノルム（大きさ）計算。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "ifWmVgbj2zbI",
        "outputId": "e3a0114a-b841-4657-f774-f76ce3e3d1f8"
      },
      "source": [
        "# userId==1が見た映画リストを抽出。\n",
        "# NaN（Not a Number）を除外したもの。\n",
        "\n",
        "print(df.loc[1]) # userId==1の視聴履歴\n",
        "print(df.loc[1].notnull()) # 値の有無\n",
        "print(df.loc[1][df.loc[1].notnull()]) # 値の有るもの\n",
        "print(df.loc[1][df.loc[1].notnull()].index) # 値の有るmovieId"
      ],
      "execution_count": 24,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "movieId\n",
            "1         4.0\n",
            "2         NaN\n",
            "3         4.0\n",
            "4         NaN\n",
            "5         NaN\n",
            "         ... \n",
            "193581    NaN\n",
            "193583    NaN\n",
            "193585    NaN\n",
            "193587    NaN\n",
            "193609    NaN\n",
            "Name: 1, Length: 9724, dtype: float64\n",
            "movieId\n",
            "1          True\n",
            "2         False\n",
            "3          True\n",
            "4         False\n",
            "5         False\n",
            "          ...  \n",
            "193581    False\n",
            "193583    False\n",
            "193585    False\n",
            "193587    False\n",
            "193609    False\n",
            "Name: 1, Length: 9724, dtype: bool\n",
            "movieId\n",
            "1       4.0\n",
            "3       4.0\n",
            "6       4.0\n",
            "47      5.0\n",
            "50      5.0\n",
            "       ... \n",
            "3744    4.0\n",
            "3793    5.0\n",
            "3809    4.0\n",
            "4006    4.0\n",
            "5060    5.0\n",
            "Name: 1, Length: 232, dtype: float64\n",
            "Int64Index([   1,    3,    6,   47,   50,   70,  101,  110,  151,  157,\n",
            "            ...\n",
            "            3671, 3702, 3703, 3729, 3740, 3744, 3793, 3809, 4006, 5060],\n",
            "           dtype='int64', name='movieId', length=232)\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "TopKwcwD6ZpU",
        "outputId": "2c4d9fad-6f5a-4af6-faff-8ef575572b3a"
      },
      "source": [
        "# 映画リストを基準にしたuserId==1の評価値を参照する方法。\n",
        "index = set(df.loc[1][df.loc[1].notnull()].index)\n",
        "df.loc[1][index]"
      ],
      "execution_count": 25,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "movieId\n",
              "1024    5.0\n",
              "1       4.0\n",
              "1025    5.0\n",
              "3       4.0\n",
              "2048    5.0\n",
              "       ... \n",
              "500     3.0\n",
              "3062    4.0\n",
              "3578    5.0\n",
              "2046    4.0\n",
              "1023    5.0\n",
              "Name: 1, Length: 232, dtype: float64"
            ]
          },
          "metadata": {},
          "execution_count": 25
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "dCqvcN4IiUeT",
        "outputId": "7f2e8ac5-5391-451a-8414-432860147b1f"
      },
      "source": [
        "# userId=1と2で重複するインデックスを抽出する方法。\n",
        "index1 = set(df.loc[1][df.loc[1].notnull()].index)\n",
        "index2 = set(df.loc[2][df.loc[2].notnull()].index)\n",
        "common_index = index1.intersection(index2)\n",
        "print(len(index1), len(index2))\n",
        "print(len(common_index))\n",
        "print(common_index)"
      ],
      "execution_count": 26,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "232 29\n",
            "2\n",
            "{3578, 333}\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "Xiwg7Vee4_Cd",
        "outputId": "ff66c200-40e1-4dbd-d08f-310c125bd461"
      },
      "source": [
        "# ユーザ間類似度は「評価値の二乗誤差」を用いることにしよう。\n",
        "# 同じ映画を見ているとは限らないため、\n",
        "# 視聴映画リストで重複している映画だけを抽出し、誤差を算出する必要がある。\n",
        "\n",
        "def get_similarity(person1, person2, dataset):\n",
        "  # person1とperson2の映画リスト\n",
        "  movies1 = dataset.loc[person1][dataset.loc[person1].notnull()].index\n",
        "  movies2 = dataset.loc[person2][dataset.loc[person2].notnull()].index\n",
        "\n",
        "  # 共通映画リスト\n",
        "  movies1 = set(movies1)\n",
        "  movies2 = set(movies2)\n",
        "  both_movies = movies1.intersection(movies2)\n",
        "\n",
        "  # 共通リストがない場合\n",
        "  if len(both_movies) == 0:\n",
        "    return 0\n",
        "  \n",
        "  #print('{}, {}: len(person1)={}, len(person2)={}, len(both_movies)={}'.format(person1, person2, len(movies1), len(movies2), len(both_movies)))\n",
        "  \n",
        "  # 共通リストがある場合\n",
        "  vector1 = np.array(dataset.loc[person1][both_movies])\n",
        "  vector2 = np.array(dataset.loc[person2][both_movies])\n",
        "  #print(type(vector1), vector1.shape)\n",
        "\n",
        "  nominator = np.dot(vector1, vector2)\n",
        "  denominator = np.linalg.norm(vector1) * np.linalg.norm(vector2)\n",
        "  similarity = nominator / denominator\n",
        "  return similarity\n",
        "\n",
        "print(get_similarity(1, 1, df)) #同じユーザ同士なら類似度1\n",
        "print(get_similarity(1, 2, df))\n",
        "print(get_similarity(2, 1, df)) #違うユーザを順番入れ替えて測っても同じ類似度が出ることを確認\n"
      ],
      "execution_count": 27,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "1.0\n",
            "0.9999999999999998\n",
            "0.9999999999999998\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "42YcysNg2zkv"
      },
      "source": [
        "### step 3: あるユーザiに対する最大類似度となるユーザjを抽出。\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "t2jVNF13CvBa",
        "outputId": "a301f067-23a0-44e7-fd92-89d3575c80d4"
      },
      "source": [
        "# コード確認用に小規模データセットを乱数で用意。\n",
        "# 乱数のため実行する度に値が変わることを確認しよう。\n",
        "data = np.random.randn(5)\n",
        "print(data)\n"
      ],
      "execution_count": 28,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "[ 0.37179124 -0.32677014  0.23904703 -0.73957128  2.1136708 ]\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "t3DAZcEPCy6F",
        "outputId": "5e4a9dbf-8b39-45fd-e6bd-65801ced028a"
      },
      "source": [
        "# トラブルシューティング等、乱数であってもそれを再現したいことがある。\n",
        "# このような場合にはシード値を与えて実行する。\n",
        "# シード値を固定しておけば何度実行しても同じ値が再現できることを確認しよう。\n",
        "np.random.seed(100) # この値（シード値）は何でも良い。\n",
        "data = np.random.randn(5)\n",
        "print(data)\n"
      ],
      "execution_count": 29,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "[-1.74976547  0.3426804   1.1530358  -0.25243604  0.98132079]\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "BjNRCFMnqHZS",
        "outputId": "36b9b9cf-cd5e-4f81-de5c-7d5e08009f62"
      },
      "source": [
        "\n",
        "# 上位k件の「未ソート」インデックス\n",
        "k = 3\n",
        "indices = np.argpartition(-data, k)[:k]\n",
        "print(indices)\n",
        "\n",
        "# 上位k件の「ソート済み」インデックス\n",
        "indices = indices[np.argsort(-data[indices])]\n",
        "print(indices)\n",
        "\n",
        "# 上位k件の値\n",
        "print(data[indices])"
      ],
      "execution_count": 30,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "[2 4 1]\n",
            "[2 4 1]\n",
            "[1.1530358  0.98132079 0.3426804 ]\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "p8iXJxJq0HgV",
        "outputId": "136542df-4875-4893-a2aa-819e2ec41892"
      },
      "source": [
        "# 大きい順にソートし、インデックスを取得\n",
        "\n",
        "def get_top_k(data, top=3):\n",
        "  indices = np.argpartition(-data, top)[:top]\n",
        "  indices = indices[np.argsort(-data[indices])]\n",
        "  return indices, data[indices]\n",
        "\n",
        "for k in range(1,4):\n",
        "  indices, top_k = get_top_k(data, k)\n",
        "  print('k', k)\n",
        "  print(indices)\n",
        "  print(top_k)\n"
      ],
      "execution_count": 31,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "k 1\n",
            "[2]\n",
            "[1.1530358]\n",
            "k 2\n",
            "[2 4]\n",
            "[1.1530358  0.98132079]\n",
            "k 3\n",
            "[2 4 1]\n",
            "[1.1530358  0.98132079 0.3426804 ]\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "CsESSP7I21BO",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "0bd96b23-892e-48c2-f47b-00de14b79e13"
      },
      "source": [
        "def get_similarities_top_k(source, dataset, k=3):\n",
        "  targets = list(dataset.index) # ユーザインデックスを取得\n",
        "\n",
        "  # 類似度保存用配列を用意\n",
        "  # 配列長を+1しているのは1番目から使うため。\n",
        "  similarities = np.zeros(len(dataset)+1)\n",
        "\n",
        "  # 全ユーザとの類似度算出\n",
        "  for opponent in targets:\n",
        "    if opponent == source:\n",
        "      similarities[opponent] = 0. #自分自身は無視する\n",
        "    else:\n",
        "      similarities[opponent] = get_similarity(source, opponent, dataset)\n",
        "  \n",
        "  # 降順ソートして上位k人のidを取得\n",
        "  indices, values = get_top_k(similarities, k)\n",
        "  return indices, values\n",
        "\n",
        "# userId==1との類似度上位ユーザを確認\n",
        "k = 3\n",
        "indices, values = get_similarities_top_k(1, df, k)\n",
        "print('k', k)\n",
        "print(indices)\n",
        "print(values)\n"
      ],
      "execution_count": 32,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "k 3\n",
            "[383 388 184]\n",
            "[1. 1. 1.]\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "UUvWm9IT21Jp"
      },
      "source": [
        "### step 4: ユーザjが高く評価している映画をリストアップ。\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "l5HVOk5M22y8",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "195978f9-f371-4461-d40d-c2058e808509"
      },
      "source": [
        "# ユーザ383の評価とそのインデックス\n",
        "user383_ratings = df.loc[383][df.loc[383].notnull()]\n",
        "user383_ratings_indices = df.loc[383][df.loc[383].notnull()].index\n",
        "print(user383_ratings[:5])\n",
        "print(user383_ratings_indices)"
      ],
      "execution_count": 33,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "movieId\n",
            "150     4.0\n",
            "539     4.0\n",
            "903     4.0\n",
            "1196    3.0\n",
            "1234    3.0\n",
            "Name: 383, dtype: float64\n",
            "Int64Index([ 150,  539,  903, 1196, 1234, 1246, 1293, 1299, 1584, 1953, 1994,\n",
            "            2324, 2396, 2436, 2445, 2447, 2496, 2501, 2506, 2539, 2541, 2546,\n",
            "            2558, 2686, 2690, 2712, 2762, 2881, 2906, 2961, 2977, 2996, 3006,\n",
            "            3115],\n",
            "           dtype='int64', name='movieId')\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "pzFH_ASDtK4o",
        "outputId": "d15888c7-c497-4f3b-adf1-16ba652db79a"
      },
      "source": [
        "# ユーザ383の上位評価を抽出\n",
        "# get_top_k は与えた配列の中における順番を返してくるため、元のインデックスに換算し直す必要がある。\n",
        "relative_indices, values = get_top_k(np.array(user383_ratings))\n",
        "print(relative_indices)\n",
        "print(values)\n",
        "\n",
        "true_indices = user383_ratings_indices[relative_indices]\n",
        "print(true_indices)\n",
        "print(user383_ratings[true_indices])"
      ],
      "execution_count": 34,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "[12  5 11]\n",
            "[5. 5. 5.]\n",
            "Int64Index([2396, 1246, 2324], dtype='int64', name='movieId')\n",
            "movieId\n",
            "2396    5.0\n",
            "1246    5.0\n",
            "2324    5.0\n",
            "Name: 383, dtype: float64\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "eruoKlBTtif3",
        "outputId": "9b30f235-789d-44e8-fc59-92fdc7644fcc"
      },
      "source": [
        "def get_top_movies(target, df):\n",
        "  # 対象ユーザの評価とそのインデックス\n",
        "  user_ratings = df.loc[target][df.loc[target].notnull()]\n",
        "  user_ratings_indices = df.loc[target][df.loc[target].notnull()].index\n",
        "\n",
        "  # 対象ユーザの上位評価\n",
        "  relative_indices, values = get_top_k(np.array(user_ratings))\n",
        "  true_indices = user_ratings_indices[relative_indices]\n",
        "  return true_indices, user_ratings[true_indices]\n",
        "\n",
        "opponent = 383\n",
        "indices, values = get_top_movies(opponent, df)\n",
        "print(indices)\n",
        "print(values)\n"
      ],
      "execution_count": 35,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Int64Index([2396, 1246, 2324], dtype='int64', name='movieId')\n",
            "movieId\n",
            "2396    5.0\n",
            "1246    5.0\n",
            "2324    5.0\n",
            "Name: 383, dtype: float64\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "rEcjXUAz228j"
      },
      "source": [
        "### step 5: リストアップした映画からユーザiが見ていないもの（＝推薦候補）を抽出。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Jh8p0CT6t2B1",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "c70a3dc8-ad1b-4022-eaa8-a86661a9d680"
      },
      "source": [
        "# userId==1の視聴映画id\n",
        "user1_indices = set(df.loc[1][df.loc[1].notnull()].index)\n",
        "print(user1_indices)\n",
        "\n",
        "# userId==383の高評価映画id\n",
        "user383_indices = set(indices)\n",
        "print(user383_indices)\n",
        "\n",
        "# 高評価idのうち、userId==1がまだ視聴していないid\n",
        "recommend_indices = user383_indices - user1_indices\n",
        "print(recommend_indices)"
      ],
      "execution_count": 36,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "{1024, 1, 1025, 3, 2048, 1029, 6, 1030, 1031, 1032, 2054, 2058, 2571, 527, 1552, 1042, 2580, 1049, 2078, 543, 3617, 1060, 1573, 2596, 552, 553, 2090, 1580, 2093, 2094, 47, 2096, 1073, 50, 1587, 2099, 3639, 1080, 2105, 2616, 2617, 1089, 1090, 2115, 1092, 2116, 70, 2628, 1097, 3147, 590, 592, 593, 1617, 2640, 596, 1620, 2641, 2644, 2648, 1625, 2137, 2139, 3671, 2141, 2654, 2143, 608, 2657, 3168, 101, 1127, 3176, 1644, 110, 1136, 2161, 3702, 3703, 2174, 2692, 648, 1676, 2700, 2193, 3729, 661, 151, 2716, 157, 3740, 3744, 673, 163, 3243, 1196, 1197, 1198, 3247, 3253, 1206, 1208, 1210, 1213, 1214, 1219, 1220, 1732, 1222, 1224, 2761, 1226, 3273, 2253, 3793, 216, 1240, 2268, 733, 223, 736, 2273, 3809, 231, 1256, 1258, 235, 2797, 1265, 1777, 2291, 1270, 1275, 1278, 1793, 1282, 260, 2826, 1291, 780, 1804, 1805, 1298, 2329, 2338, 804, 296, 2858, 2353, 2872, 3386, 316, 2366, 1348, 333, 2387, 2899, 2389, 2395, 349, 1377, 356, 2916, 2406, 362, 2414, 367, 3439, 3440, 3441, 1396, 3448, 3450, 2427, 1408, 1920, 2944, 2947, 2948, 2949, 1927, 2959, 2450, 919, 3479, 923, 2459, 3489, 1954, 1445, 2470, 423, 4006, 2985, 2987, 940, 2478, 943, 1967, 2991, 2993, 2997, 441, 954, 2492, 1473, 5060, 2502, 3527, 457, 2000, 2005, 3033, 3034, 1500, 2012, 480, 2528, 2018, 2529, 2028, 1517, 2542, 3052, 3053, 1009, 2033, 500, 3062, 3578, 2046, 1023}\n",
            "{2396, 2324, 1246}\n",
            "{2396, 2324, 1246}\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "byHy9hVgt2OC",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "50205847-60b3-410a-d396-5565c16922bb"
      },
      "source": [
        "def get_recommendation(source, opponent_indices, df):\n",
        "  # userId==sourceの視聴映画id\n",
        "  source_indices = set(df.loc[source][df.loc[source].notnull()].index)\n",
        "\n",
        "  # 対象ユーザの高評価映画id\n",
        "  opponent_indices = set(opponent_indices)\n",
        "\n",
        "  # 高評価idのうち、userId==sourceがまだ視聴していないid\n",
        "  recommend_indices = opponent_indices - source_indices\n",
        "  return recommend_indices\n",
        "\n",
        "userId = 1\n",
        "opponent = 383\n",
        "opponent_indices, values = get_top_movies(opponent, df)\n",
        "recommend_indices = get_recommendation(userId, opponent_indices, df)\n",
        "print(recommend_indices)\n",
        "\n",
        "userId = 1\n",
        "opponent = 388\n",
        "opponent_indices, values = get_top_movies(opponent, df)\n",
        "recommend_indices = get_recommendation(userId, opponent_indices, df)\n",
        "print(recommend_indices)\n"
      ],
      "execution_count": 37,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "{2396, 2324, 1246}\n",
            "{8360, 4306, 33615}\n"
          ]
        }
      ]
    }
  ]
}