すべてのプロダクト
Search
ドキュメントセンター

MaxCompute:はじめに

最終更新日:Mar 21, 2025

このトピックでは、DataFrame オブジェクトを作成および管理する方法と、DataFrame を使用してデータを処理する方法について説明します。

データの準備

このトピックでは、u.useru.item、および u.data を例として使用します。 u.user ファイルにはユーザー関連のデータが格納されています。 u.item ファイルには映画関連のデータが格納されています。 u.data ファイルには評価関連のデータが格納されています。

  1. 次の表を作成します。

    • pyodps_ml_100k_users: ユーザー関連のデータを格納します。

      CREATE TABLE IF NOT EXISTS pyodps_ml_100k_users
      (
        user_id    BIGINT COMMENT 'ユーザー ID',
        age        BIGINT COMMENT '年齢',
        sex        STRING COMMENT '性別',
        occupation STRING COMMENT '職業',
        zip_code   STRING COMMENT '郵便番号'
      );
    • pyodps_ml_100k_movies: 映画関連のデータを格納します。

      CREATE TABLE IF NOT EXISTS pyodps_ml_100k_movies
      (
          movie_id            BIGINT COMMENT '映画 ID',
          title              STRING COMMENT '映画タイトル',
          release_date       STRING COMMENT '公開日',
          video_release_date STRING COMMENT 'ビデオ発売日',
          IMDb_URL           STRING COMMENT 'IMDb URL',
          unknown            TINYINT COMMENT '不明',
          Action             TINYINT COMMENT 'アクション',
          Adventure          TINYINT COMMENT '冒険',
          Animation          TINYINT COMMENT 'アニメーション',
          Children           TINYINT COMMENT '子供向け',
          Comedy             TINYINT COMMENT 'コメディ',
          Crime              TINYINT COMMENT '犯罪',
          Documentary        TINYINT COMMENT 'ドキュメンタリー',
          Drama              TINYINT COMMENT 'ドラマ',
          Fantasy            TINYINT COMMENT 'ファンタジー',
          FilmNoir           TINYINT COMMENT 'フィルム・ノワール',
          Horror             TINYINT COMMENT 'ホラー',
          Musical            TINYINT COMMENT '音楽',
          Mystery            TINYINT COMMENT 'ミステリー',
          Romance            TINYINT COMMENT 'ロマンス',
          SciFi              TINYINT COMMENT 'SF',
          Thriller           TINYINT COMMENT 'スリラー',
          War                TINYINT COMMENT '戦争',
          Western            TINYINT COMMENT '西部劇'
      );
    • pyodps_ml_100k_ratings: 評価関連のデータを格納します。

      CREATE TABLE IF NOT EXISTS pyodps_ml_100k_ratings
      (
          user_id    BIGINT COMMENT 'ユーザー ID',
          movie_id  BIGINT COMMENT '映画 ID',
          rating    BIGINT COMMENT 'スコア',
          timestamp BIGINT COMMENT 'タイムスタンプ'
      )
  2. コマンドを実行して、ファイルのデータを MaxCompute テーブルにインポートします。トンネルコマンドの詳細については、 をご参照ください。トンネルアップロードコマンドを使用して、ファイルのデータを MaxCompute テーブルにインポートします。Tunnel コマンドの詳細については、「トンネル コマンド

    Tunnel upload -fd | path_to_file/u.user pyodps_ml_100k_users;
    Tunnel upload -fd | path_to_file/u.item pyodps_ml_100k_movies;
    Tunnel upload -fd | path_to_file/u.data pyodps_ml_100k_ratings;

DataFrame オブジェクトに対する操作の実行

このトピックでは、pyodps_ml_100k_movies(映画関連データ)、pyodps_ml_100k_users(ユーザー関連データ)、pyodps_ml_100k_ratings(評価関連データ)の各テーブルを使用します。次の例は、IPython でこれらのテーブルに対して操作を実行する方法を示しています。

説明

IPython を使用する前に、Python がインストールされていることを確認してください。 IPython は Python をベースに開発されています。 Python 環境をインストールする必要があります。 Python 環境がインストールされた後、pip install IPython を使用して IPython をインストールできます。インストールが完了したら、IPython コマンドを実行して、IPython ベースのインタラクティブ環境を起動できます。その後、Python コードを作成して実行できます。

  1. MaxCompute オブジェクトを作成します。

    import os
    from odps import ODPS
    # 環境変数 ALIBABA_CLOUD_ACCESS_KEY_ID を Alibaba Cloud アカウントの AccessKey ID に設定します。
    # 環境変数 ALIBABA_CLOUD_ACCESS_KEY_SECRET を Alibaba Cloud アカウントの AccessKey シークレットに設定します。
    # AccessKey ID または AccessKey シークレットを直接使用しないことをお勧めします。
    o = ODPS(
        os.getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'),
        os.getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
        project='your-default-project',
        endpoint='your-end-point',
    )
    
  2. テーブルを指定して DataFrame オブジェクトを作成します。

    from odps.df import DataFrame
    users = DataFrame(o.get_table('pyodps_ml_100k_users'));
  3. dtypes プロパティをクエリして、DataFrame オブジェクトのフィールドとフィールドのデータ型を表示します。

    print(users.dtypes)

    次の結果が返されます。

    odps.Schema {
      user_id             int64
      age                 int64
      sex                 string
      occupation          string
      zip_code            string
    }
  4. head メソッドを使用して、最初の N 行のデータを取得し、簡単なプレビューを表示します。

    print(users.head(10))

    次の結果が返されます。

       user_id  age  sex     occupation  zip_code
    0        1   24    M     technician     85711
    1        2   53    F          other     94043
    2        3   23    M         writer     32067
    3        4   24    M     technician     43537
    4        5   33    F          other     15213
    5        6   42    M      executive     98101
    6        7   57    M  administrator     91344
    7        8   36    M  administrator     05201
    8        9   29    M        student     01002
    9       10   53    M         lawyer     90703
  5. すべてのフィールドを表示したくない場合は、次の操作を実行します。

    • クエリするフィールドを指定します。

      print(users[['user_id', 'age']].head(5))

      次の結果が返されます。

         user_id  age
      0        1   24
      1        2   53
      2        3   23
      3        4   24
      4        5   33
    • 特定のフィールドを除外します。

      print(users.exclude('zip_code', 'age').head(5))

      次の結果が返されます。

         user_id  sex  occupation
      0        1    M  technician
      1        2    F       other
      2        3    M      writer
      3        4    M  technician
      4        5    F       other
    • 特定のフィールドを除外し、計算に基づいて新しいフィールドを追加します。たとえば、sex_bool フィールドを追加し、sexM の場合、sex_bool を True に設定します。 sex の値が M でない場合は、sex_bool を False に設定します。

      print(users.select(users.exclude('zip_code', 'sex'), sex_bool=users.sex == 'M').head(5))

      次の結果が返されます。

         user_id  age  occupation  sex_bool
      0        1   24  technician      True
      1        2   53       other     False
      2        3   23      writer      True
      3        4   24  technician      True
      4        5   33       other     False
  6. 男性ユーザーと女性ユーザーの数を取得します。

    print(users.groupby(users.sex).agg(count=users.count()))

    次の結果が返されます。

       sex  count
    0    F    273
    1    M    670
  7. ユーザーを職業別に分類し、ユーザー数が最も多い上位 10 件の職業を取得し、ユーザー数に基づいて降順にソートします。

    df = users.groupby('occupation').agg(count=users['occupation'].count())
    df1 = df.sort(df['count'], ascending=False)
    print(df1.head(10))

    次の結果が返されます。

          occupation  count
    0        student    196
    1          other    105
    2       educator     95
    3  administrator     79
    4       engineer     67
    5     programmer     66
    6      librarian     51
    7         writer     45
    8      executive     32
    9      scientist     31

    または、value_counts メソッドを使用することもできます。このメソッドによって返されるレコードの数は、options.df.odps.sort.limit パラメーターによって制限されます。詳細については、「構成」をご参照ください。

    df = users.occupation.value_counts()[:10]
    print(df.head(10)) 

    次の結果が返されます。

          occupation  count
    0        student    196
    1          other    105
    2       educator     95
    3  administrator     79
    4       engineer     67
    5     programmer     66
    6      librarian     51
    7         writer     45
    8      executive     32
    9      scientist     31
  8. 3 つのテーブルを 結合 し、pyodps_ml_100k_lens という名前の新しいテーブルとして保存します。

    movies = DataFrame(o.get_table('pyodps_ml_100k_movies'))
    ratings = DataFrame(o.get_table('pyodps_ml_100k_ratings'))
    
    o.delete_table('pyodps_ml_100k_lens', if_exists=True)
    lens = movies.join(ratings).join(users).persist('pyodps_ml_100k_lens')
    
    print(lens.dtypes)

    次の結果が返されます。

    odps.Schema {
      movie_id                          int64       
      title                             string      
      release_date                      string      
      ideo_release_date                 string      
      imdb_url                          string      
      unknown                           int64       
      action                            int64       
      adventure                         int64       
      animation                         int64       
      children                          int64       
      comedy                            int64       
      crime                             int64       
      documentary                       int64       
      drama                             int64       
      fantasy                           int64       
      filmnoir                          int64       
      horror                            int64       
      musical                           int64       
      mystery                           int64       
      romance                           int64       
      scifi                             int64       
      thriller                          int64       
      war                               int64       
      western                           int64       
      user_id                           int64       
      rating                            int64       
      timestamp                         int64       
      age                               int64       
      sex                               string      
      occupation                        string      
      zip_code                          string      
    }

DataFrame を使用したデータ処理

次の手順を実行する前に、Iris データセットをダウンロードしてください。この例では、DataWorks PyODPS ノードが使用されています。詳細については、「PyODPS 3 タスクの開発」をご参照ください。

  1. テストデータを格納するためのテーブルを作成します。

    DataWorks のテーブル管理機能を使用してテーブルを作成します。

    1. 「ビジネスフロー」セクションで目的のワークフローをクリックし、MaxComputeテーブルの作成テーブルの作成パス名前作成 を右クリックして、 を選択します。 ダイアログボックスで、 ドロップダウンリストからパスを選択し、 フィールドに名前を入力して、 をクリックします。

    2. テーブル編集ページの左上隅にある image.png アイコンをクリックします。

    3. 次のステートメントを実行してテーブルを作成します。

      CREATE TABLE pyodps_iris (
          sepallength double COMMENT 'がく片の長さ (cm)',
          sepalwidth double COMMENT 'がく片の幅 (cm)',
          petallength double COMMENT '花びらの長さ (cm)',
          petalwidth double COMMENT '花びらの幅 (cm)',
          name string COMMENT '名前'
      ) ;
  2. テストデータをアップロードします。

    1. 作成したテーブルの名前を右クリックし、[データのインポート] を選択します。 [データインポートウィザード] ダイアログボックスで、[データのインポート][データインポートウィザード] をクリックします。次に、 をクリックして、ダウンロードしたデータセットをアップロードします。

      image

    2. [場所別に一致] を選択し、[インポート データ] をクリックします。

  3. 目的のワークフローをクリックし、MaxCompute を右クリックして、[ノードの作成] > [PyODPS 3] を選択し、コードを保存して実行するための PyODPS ノードを作成します。

  4. コードを記述し、image.png アイコンをクリックします。下部ペインの [ランタイムログ] セクションで結果を確認できます。コードの詳細:

    from odps import ODPS
    from odps.df import DataFrame, output
    import os
    
    # ALIBABA_CLOUD_ACCESS_KEY_ID 環境変数がユーザーの AccessKey ID に設定され、
    # ALIBABA_CLOUD_ACCESS_KEY_SECRET 環境変数がユーザーの AccessKey シークレットに設定されていることを確認します。
    # AccessKey ID と AccessKey シークレットの文字列を直接使用することはお勧めしません。
    o = ODPS(
        os.getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'),
        os.getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
        project='your-default-project',
        endpoint='your-end-point',
    )
    # MaxCompute テーブルから DataFrame オブジェクト iris を作成します。
    iris = DataFrame(o.get_table('pyodps_iris'))
    print(iris.head(10))
    # iris コンテンツの一部を表示します。
    print(iris.sepallength.head(5))
    
    # ユーザー定義関数を使用して、iris の 2 つの列の合計を計算します。
    print(iris.apply(lambda row: row.sepallength + row.sepalwidth, axis=1, reduce=True, types='float').rename('sepaladd').head(3))
    
    # 関数の出力名と型を指定します。
    @output(['iris_add', 'iris_sub'], ['float', 'float'])
    def handle(row):
        # yield キーワードを使用して、複数の行の結果を返します。
        yield row.sepallength - row.sepalwidth, row.sepallength + row.sepalwidth
        yield row.petallength - row.petalwidth, row.petallength + row.petalwidth
    
    # 最初の 5 行の結果を表示します。 axis=1 は、列の軸が水平方向に拡張されることを示します。
    print(iris.apply(handle, axis=1).head(5))

    次の結果が返されます。

    # print(iris.head(10))
       sepallength  sepalwidth  petallength  petalwidth         name
    0          4.9         3.0          1.4         0.2  Iris-setosa
    1          4.7         3.2          1.3         0.2  Iris-setosa
    2          4.6         3.1          1.5         0.2  Iris-setosa
    3          5.0         3.6          1.4         0.2  Iris-setosa
    4          5.4         3.9          1.7         0.4  Iris-setosa
    5          4.6         3.4          1.4         0.3  Iris-setosa
    6          5.0         3.4          1.5         0.2  Iris-setosa
    7          4.4         2.9          1.4         0.2  Iris-setosa
    8          4.9         3.1          1.5         0.1  Iris-setosa
    9          5.4         3.7          1.5         0.2  Iris-setosa
    
    
    # print(iris.sepallength.head(5))
       sepallength
    0          4.9
    1          4.7
    2          4.6
    3          5.0
    4          5.4
    
    # print(iris.apply(lambda row: row.sepallength + row.sepalwidth, axis=1, reduce=True, types='float').rename('sepaladd').head(3))
       sepaladd
    0       7.9
    1       7.9
    2       7.7
    
    # print(iris.apply(handle,axis=1).head(5))
       iris_add  iris_sub
    0       1.9       7.9
    1       1.2       1.6
    2       1.5       7.9
    3       1.1       1.5
    4       1.5       7.7