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

MaxCompute:データのマージ

最終更新日:Jan 08, 2025

このトピックでは、Alibaba Cloud MaxCompute SDK for Python (PyODPS) DataFrameでサポートされている、テーブル内のデータをマージする結合および結合操作について説明します。

前提条件

テーブルデータがインポートされます。 入門の「データの準備」セクションの指示に基づいてデータをダウンロードできます。 次のコードは、テーブルの構造を示しています。

>>> from odps.df import DataFrame
>>> movies = DataFrame(o.get_table('pyodps_ml_100k_movies'))
>>> ratings = DataFrame(o.get_table('pyodps_ml_100k_ratings'))

>>> movies.dtypes
odps.Schema {
  movie_id                            int64
  title                               string
  release_date                        string
  video_release_date                  string
  _url                            string
}

>>> ratings.dtypes
odps.Schema {
  user_id                     int64
  movie_id                    int64
  rating                      int64
  unix_timestamp              int64
}

結合操作

PyODPS DataFrameでは、2つのコレクションオブジェクトを結合できます。

  • join条件を指定しない場合、DataFrame APIは同じ名前の列を使用してCollectionオブジェクトを結合します。

    >>> movies.join(ratings).head(3)
       movie_id              title  release_date  video_release_date                                           url  user_id  rating  unix_timestamp
    0         3  Four Rooms (1995)   01-Jan-1995                      http://example.aliyundoc.com/M/title-exact?Four%20Rooms%...       49       3       888068877
    1         3  Four Rooms (1995)   01-Jan-1995                      http://example.aliyundoc.com/M/title-exact?Four%20Rooms%...      621       5       881444887
    2         3  Four Rooms (1995)   01-Jan-1995                      http://example.aliyundoc.com/M/title-exact?Four%20Rooms%...      291       3       874833936
  • join条件を明示的に指定できます。 join操作の場合、2つのDataFrameオブジェクトのon conditionで指定された列名が同じ場合、システムは新しいテーブルの2つのテーブルのいずれかで指定された列を使用します。

    >>> movies.join(ratings, on='movie_id').head(3)
       movie_id              title  release_date  video_release_date                                            url  user_id  rating  unix_timestamp
    0         3  Four Rooms (1995)   01-Jan-1995                      http://example.aliyundoc.com/M/title-exact?Four%20Rooms%...       49       3       888068877
    1         3  Four Rooms (1995)   01-Jan-1995                      http://example.aliyundoc.com/M/title-exact?Four%20Rooms%...      621       5       881444887
    2         3  Four Rooms (1995)   01-Jan-1995                      http://example.aliyundoc.com/M/title-exact?Four%20Rooms%...      291       3       874833936
  • left joinなどの他のタイプのjoin操作の場合、2つのCollectionオブジェクトのon条件で指定された列名が同じ場合、システムは新しいテーブルの指定された列の名前を変更します。

    >>> movies.left_join(ratings, on='movie_id').head(3)
       movie_id_x              title  release_date  video_release_date                                           url  user_id  movie_id_y  rating  unix_timestamp
    0           3  Four Rooms (1995)   01-Jan-1995                      http://example.aliyundoc.com/M/title-exact?Four%20Rooms%...       49           3       3       888068877
    1           3  Four Rooms (1995)   01-Jan-1995                      http://example.aliyundoc.com/M/title-exact?Four%20Rooms%...      621           3       5       881444887
    2           3  Four Rooms (1995)   01-Jan-1995                      http://example.aliyundoc.com/M/title-exact?Four%20Rooms%...      291           3       3       874833936

    上記のサンプルコードでは、2つのmovie_id列の名前がmovie_id_xおよびmovie_id_yに変更されています。 名前変更ルールは、suffixesパラメーターによって異なります。 サフィックスパラメーターのデフォルト値は ('_x', '_y') です。 同じ名前の列が見つかった場合、システムは指定されたサフィックスを使用して列の名前を変更します。

    >>> ratings2 = ratings[ratings.exclude('movie_id'), ratings.movie_id.rename('movie_id2')]
    >>> ratings2.dtypes
    odps.Schema {
      user_id                     int64
      rating                      int64
      unix_timestamp              int64
      movie_id2                   int64
    }
    >>> movies.join(ratings2, on=[('movie_id', 'movie_id2')]).head(3)
       movie_id              title  release_date  video_release_date                                           url  user_id  rating  unix_timestamp  movie_id2
    0         3  Four Rooms (1995)   01-Jan-1995                      http://example.aliyundoc.com/M/title-exact?Four%20Rooms%...       49       3       888068877          3
    1         3  Four Rooms (1995)   01-Jan-1995                      http://example.aliyundoc.com/M/title-exact?Four%20Rooms%...      621       5       881444887          3
    2         3  Four Rooms (1995)   01-Jan-1995                      http://example.aliyundoc.com/M/title-exact?Four%20Rooms%...      291       3       874833936          3
  • また、新しいテーブルの列の名前を変更するためon、条件の等しい演算子を使用する式を指定することもできます。

    >>> movies.join(ratings2, on=[movies.movie_id == ratings2.movie_id2]).head(3)
       movie_id              title  release_date  video_release_date                                           url  user_id  rating  unix_timestamp  movie_id2
    0         3  Four Rooms (1995)   01-Jan-1995                      http://example.aliyundoc.com/M/title-exact?Four%20Rooms%...       49       3       888068877          3
    1         3  Four Rooms (1995)   01-Jan-1995                      http://example.aliyundoc.com/M/title-exact?Four%20Rooms%...      621       5       881444887          3
    2         3  Four Rooms (1995)   01-Jan-1995                      http://example.aliyundoc.com/M/title-exact?Four%20Rooms%...      291       3       874833936          3
  • self join操作を実行する場合は、viewメソッドを呼び出して、左右のテーブルから列を取得できます。

    >>> movies2 = movies.view()
    >>> movies.join(movies2, movies.movie_id == movies2.movie_id)[movies, movies2.movie_id.rename('movie_id2')].head(3)
       movie_id            title_x release_date_x video_release_date_x  \
    0         2   GoldenEye (1995)    01-Jan-1995                 True
    1         3  Four Rooms (1995)    01-Jan-1995                 True
    2         4  Get Shorty (1995)    01-Jan-1995                 True
    
                                              url_x  movie_id2
    0  http://example.aliyundoc.com/M/title-exact?GoldenEye%20(...          2
    1  http://example.aliyundoc.comtitle-exact?Four%20Rooms%...          3
    2  http://example.aliyundoc.com/M/title-exact?Get%20Shorty%...          4

    PyODPS DataFrameは、join操作に加えて、left joinright join、およびouter join操作をサポートします。 左結合、右結合、および外側結合操作では、名前が変更された列の末尾にデフォルトで _xまたは _yが付いています。 2tupleを使用して、suffixesパラメーターのサフィックスを定義できます。

  • left join、right join、またはouter join操作を実行すると、merge_columnsパラメーターをTrueに設定して、新しいテーブルで列が重複しないようにすることができます。 次に、システムは、重複列からnull以外の値を新しい列の値として選択します。

    >>> movies.left_join(ratings, on='movie_id', merge_columns=True)

mapjoin操作を実行する場合は、mapjoinをTrueに設定します。 次に、システムは右側のテーブルに対してmapjoin操作を実行します。 PyODPSコレクションとPandasコレクションに対して別々にjoin操作を実行できます。 PyODPSコレクションとデータベースコレクションでjoin操作を別々に実行することもできます。 この場合、計算はPyODPSで行われる。

組合作戦

2つのテーブルのフィールドとフィールドタイプが同じである場合、2つのテーブルのフィールドシーケンスが同じであるかどうかに関係なく、unionまたはconcatを使用して2つのテーブルを1つのテーブルにマージできます。

>>> mov1 = movies[movies.movie_id < 3]['movie_id', 'title']
>>> mov2 = movies[(movies.movie_id > 3) & (movies.movie_id < 6)]['title', 'movie_id']
>>> mov1.union(mov2)
   movie_id              title
0         1   Toy Story (1995)
1         2   GoldenEye (1995)
2         4  Get Shorty (1995)
3         5     Copycat (1995)

PyODPSコレクションとPandasコレクションに対して別々にunion操作を実行できます。 PyODPSコレクションとデータベースコレクションでunion操作を別々に実行することもできます。 この場合、計算はPyODPSで行われる。