CollectionExpr は PyODPS DataFrame API における2次元データセットを表し、MaxCompute テーブルやスプレッドシートに相当します。DataFrame オブジェクトも CollectionExpr オブジェクトです。CollectionExpr は、列操作、データフィルタリング、データ変換をサポートします。
前提条件
開始する前に、以下を確認してください。
-
pyodps_irisという名前のテーブル。詳細については、「クイックスタート」の「DataFrame データ処理」セクションをご参照ください。 -
DataFrame オブジェクト。詳細については、「DataFrame オブジェクトの作成」の「MaxCompute テーブルから DataFrame オブジェクトを作成する」セクションをご参照ください。
列の型の取得
dtypes 属性を使用して、CollectionExpr 内のすべての列の型を取得します。これはスキーマタイプを返します。
print(iris.dtypes)
出力:
odps.Schema {
sepallength float64
sepalwidth float64
petallength float64
petalwidth float64
name string
}
列の選択、追加、削除
次の表は、目的に応じて使用する構文を示しています。
| 目的 | 推奨構文 | PyODPS バージョン |
|---|---|---|
| 特定の列を選択 | expr[col1, col2] |
すべてのバージョン |
| 列を除外 | exclude(col1, col2) |
すべてのバージョン |
| 計算列を追加 | iris['new_col'] = expr |
0.7.2 以降 |
| 既存の列を上書き | iris['col'] = new_expr |
0.7.2 以降 |
| 列を削除 | del iris['col'] |
0.7.2 以降 |
| 条件付きで列を更新 | iris[condition, 'col'] = expr |
0.7.2 以降 |
| 定数列を追加 | iris['col'] = value |
0.7.12 以降 |
| 選択時に名前を変更 | select(col, new_name=expr) |
すべてのバージョン |
列の選択
expr[columns] を使用して、CollectionExpr から特定の列を選択します。
print(iris['name', 'sepallength'].head(5))
出力:
name sepallength
0 Iris-setosa 4.9
1 Iris-setosa 4.7
2 Iris-setosa 4.6
3 Iris-setosa 5.0
4 Iris-setosa 5.4
単一の列を選択して (Sequence ではなく) Collection を返すには、末尾にカンマを追加するか、二重括弧を使用します (`iris[iris.sepallength,]` または `iris[[iris.sepallength]]`)。これらがない場合、代わりに Sequence オブジェクトが返されます。
列の削除
exclude の使用 (すべての PyODPS バージョン):
print(iris.exclude('sepallength', 'petallength')[:5].head(5))
出力:
sepalwidth petalwidth name
0 3.0 0.2 Iris-setosa
1 3.2 0.2 Iris-setosa
2 3.1 0.2 Iris-setosa
3 3.6 0.2 Iris-setosa
4 3.9 0.4 Iris-setosa
del の使用 (PyODPS 0.7.2 以降):
del iris['sepallength']
del iris['petallength']
print(iris[:5].head(5))出力:
sepalwidth petalwidth name
0 3.0 0.2 Iris-setosa
1 3.2 0.2 Iris-setosa
2 3.1 0.2 Iris-setosa
3 3.6 0.2 Iris-setosa
4 3.9 0.4 Iris-setosa
列の追加
代入構文の使用 (PyODPS 0.7.2 以降、推奨):
iris['sepalwidthplus1'] = iris.sepalwidth + 1
print(iris.head(5))
出力:
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
sepalwidthplus1
0 4.0
1 4.2
2 4.1
3 4.6
4 4.9
expr[expr, new_sequence] の使用 (すべてのバージョン):追加の列が付加された新しい Collection を作成します。新しい列が既存の列と同じ名前を持つ場合は、競合を避けるために名前を変更してください。
print(iris[iris, (iris.sepalwidth + 1).rename('sepalwidthplus1')].head(5))
出力:
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
sepalwidthplus1
0 4.0
1 4.2
2 4.1
3 4.6
4 4.9
列の追加と削除の同時実行
既存の列の上書き (PyODPS 0.7.2 以降):
iris['sepalwidth'] = iris.sepalwidth * 2
print(iris.head(5))
出力:
sepallength sepalwidth petallength petalwidth name
0 4.9 6.0 1.4 0.2 Iris-setosa
1 4.7 6.4 1.3 0.2 Iris-setosa
2 4.6 6.2 1.5 0.2 Iris-setosa
3 5.0 7.2 1.4 0.2 Iris-setosa
4 5.4 7.8 1.7 0.4 Iris-setosa
exclude と新しい列の使用 (すべてのバージョン):元の列を除外し、変換後のバージョンを追加するため、名前の変更は不要です。
print(iris[iris.exclude('sepalwidth'), iris.sepalwidth * 2].head(5))
出力:
sepallength petallength petalwidth name sepalwidth
0 4.9 1.4 0.2 Iris-setosa 6.0
1 4.7 1.3 0.2 Iris-setosa 6.4
2 4.6 1.5 0.2 Iris-setosa 6.2
3 5.0 1.4 0.2 Iris-setosa 7.2
4 5.4 1.7 0.4 Iris-setosa 7.8
select の使用 (すべてのバージョン):exclude と新しい列の使用に似ていますが、キーワード引数を使用して 1 ステップで結果の名前を変更できます。
print(iris.select('name', sepalwidthminus1=iris.sepalwidth - 1).head(5))
出力:
name sepalwidthminus1
0 Iris-setosa 2.0
1 Iris-setosa 2.2
2 Iris-setosa 2.1
3 Iris-setosa 2.6
4 Iris-setosa 2.9
ラムダ式の使用:前の操作の結果をパラメーターとして受け取るラムダを渡します。PyODPS はラムダを評価し、その Collection から有効な列を代入します。
print(iris['name', 'petallength'][[lambda x: x.name]].head(5))
出力:
name
0 Iris-setosa
1 Iris-setosa
2 Iris-setosa
3 Iris-setosa
4 Iris-setosa
条件付き列更新 (PyODPS 0.7.2 以降):条件に一致する行の列のみを更新します。
iris[iris.sepallength > 5.0, 'sepalwidth'] = iris.sepalwidth * 2
print(iris.head(5))
出力:
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 7.8 1.7 0.4 Iris-setosa
定数と乱数の導入
定数列の追加
単純な構文 (PyODPS 0.7.12 以降、推奨):リテラル値を新しい列に直接割り当てます。
iris['id'] = 1
print(iris.head(5))
出力:
sepallength sepalwidth petallength petalwidth name id
0 4.9 3.0 1.4 0.2 Iris-setosa 1
1 4.7 3.2 1.3 0.2 Iris-setosa 1
2 4.6 3.1 1.5 0.2 Iris-setosa 1
3 5.0 3.6 1.4 0.2 Iris-setosa 1
4 5.4 3.9 1.7 0.4 Iris-setosa 1
単純な構文では、null 値の型を自動的に推論できません。null 列を追加するには、明示的な型を持つ NullScalar を使用してください。from odps.df import NullScalar
iris['null_col'] = NullScalar('float')
print(iris.head(5))
出力:
sepallength sepalwidth petallength petalwidth name null_col
0 4.9 3.0 1.4 0.2 Iris-setosa None
1 4.7 3.2 1.3 0.2 Iris-setosa None
2 4.6 3.1 1.5 0.2 Iris-setosa None
3 5.0 3.6 1.4 0.2 Iris-setosa None
4 5.4 3.9 1.7 0.4 Iris-setosa None
`Scalar` の使用 (すべてのバージョン): 定数を Scalar でラップし、列名を手動で指定します。
from odps.df import Scalar
print(iris[iris, Scalar(1).rename('id')][:5].head(5))
出力:
sepallength sepalwidth petallength petalwidth name id
0 4.9 3.0 1.4 0.2 Iris-setosa 1
1 4.7 3.2 1.3 0.2 Iris-setosa 1
2 4.6 3.1 1.5 0.2 Iris-setosa 1
3 5.0 3.6 1.4 0.2 Iris-setosa 1
4 5.4 3.9 1.7 0.4 Iris-setosa 1
明示的な型を持つ null 列を追加するには:
from odps.df import NullScalar
print(iris[iris, NullScalar('float').rename('fid')][:5].head(5))
出力:
sepallength sepalwidth petallength petalwidth name fid
0 4.9 3.0 1.4 0.2 Iris-setosa None
1 4.7 3.2 1.3 0.2 Iris-setosa None
2 4.6 3.1 1.5 0.2 Iris-setosa None
3 5.0 3.6 1.4 0.2 Iris-setosa None
4 5.4 3.9 1.7 0.4 Iris-setosa None
乱数列の追加
RandomScalar を使用して、0~1 の範囲のランダムな FLOAT 値の列を追加します。各行には一意の値が設定されます。オプションのパラメーターはランダムシードです。
from odps.df import RandomScalar
iris[iris, RandomScalar().rename('rand_val')][:5]
出力:
sepallength sepalwidth petallength petalwidth name rand_val
0 4.9 3.0 1.4 0.2 Iris-setosa 0.000471
1 4.7 3.2 1.3 0.2 Iris-setosa 0.799520
2 4.6 3.1 1.5 0.2 Iris-setosa 0.834609
3 5.0 3.6 1.4 0.2 Iris-setosa 0.106921
4 5.4 3.9 1.7 0.4 Iris-setosa 0.763442
データのフィルタリング
標準演算子、filter メソッド、query メソッド、またはラムダ式を使用して行をフィルタリングします。
標準のフィルター式では、AND には&、OR には|を使用します。Python のandおよびorキーワードはサポートされていません。queryメソッドは両方を受け入れます。
条件によるフィルタリング:
print(iris[iris.sepallength > 5].head(5))
出力:
sepallength sepalwidth petallength petalwidth name
0 5.4 3.9 1.7 0.4 Iris-setosa
1 5.4 3.7 1.5 0.2 Iris-setosa
2 5.8 4.0 1.2 0.2 Iris-setosa
3 5.7 4.4 1.5 0.4 Iris-setosa
4 5.4 3.9 1.3 0.4 Iris-setosa
AND (`&`):
print(iris[(iris.sepallength < 5) & (iris['petallength'] > 1.5)].head(5))
出力:
sepallength sepalwidth petallength petalwidth name
0 4.8 3.4 1.6 0.2 Iris-setosa
1 4.8 3.4 1.9 0.2 Iris-setosa
2 4.7 3.2 1.6 0.2 Iris-setosa
3 4.8 3.1 1.6 0.2 Iris-setosa
4 4.9 2.4 3.3 1.0 Iris-versicolor
OR (`|`):
print(iris[(iris.sepalwidth < 2.5) | (iris.sepalwidth > 4)].head(5))
出力:
sepallength sepalwidth petallength petalwidth name
0 5.7 4.4 1.5 0.4 Iris-setosa
1 5.2 4.1 1.5 0.1 Iris-setosa
2 5.5 4.2 1.4 0.2 Iris-setosa
3 4.5 2.3 1.3 0.3 Iris-setosa
4 5.5 2.3 4.0 1.3 Iris-versicolor
NOT (`~`):
print(iris[~(iris.sepalwidth > 3)].head(5))
出力:
sepallength sepalwidth petallength petalwidth name
0 4.9 3.0 1.4 0.2 Iris-setosa
1 4.4 2.9 1.4 0.2 Iris-setosa
2 4.8 3.0 1.4 0.1 Iris-setosa
3 4.3 3.0 1.1 0.1 Iris-setosa
4 5.0 3.0 1.6 0.2 Iris-setosa
複数の条件を指定した `filter` メソッド: filter に複数の引数を渡すことは、& でそれらを結合することと同等です。
print(iris.filter(iris.sepalwidth > 3.5, iris.sepalwidth < 4).head(5))
出力:
sepallength sepalwidth petallength petalwidth name
0 5.0 3.6 1.4 0.2 Iris-setosa
1 5.4 3.9 1.7 0.4 Iris-setosa
2 5.4 3.7 1.5 0.2 Iris-setosa
3 5.4 3.9 1.3 0.4 Iris-setosa
4 5.7 3.8 1.7 0.3 Iris-setosa
連鎖操作のためのラムダ式:
print(iris[iris.sepalwidth > 3.8]['name', lambda x: x.sepallength + 1].head(5))
出力:
name sepallength
0 Iris-setosa 6.4
1 Iris-setosa 6.8
2 Iris-setosa 6.7
3 Iris-setosa 6.4
4 Iris-setosa 6.2
フィルターとしての BOOLEAN 列:Collection に BOOLEAN 列が含まれている場合、その列を直接フィルター条件として使用します。
# スキーマの確認
print(df.dtypes)
# odps.Schema {
# a boolean
# b int64
# }
# BOOLEAN 列を使用したフィルタリング
print(df[df.a])
# a b
# 0 True 1
# 1 True 3
次の例は、単一の列を取得する場合と、それをフィルターとして使用する場合の違いを示しています。
df[df.a, ] # 1列の Collection を取得
df[[df.a]] # 1列の Collection を取得
df.select(df.a) # 1列の Collection を明示的に取得
df[df.a] # 列 a (BOOLEAN) をフィルター条件として使用
df.a # Collection から列を取得
df['a'] # Collection から列を取得
query を使用したフィルタリング
query メソッドは、Pandas と同様に、フィルター条件を文字列式として受け入れます。文字列内で列名を直接参照し、ローカル変数には @ プレフィックスを付けます。
print(iris.query("(sepallength < 5) and (petallength > 1.5)").head(5))
出力:
sepallength sepalwidth petallength petalwidth name
0 4.8 3.4 1.6 0.2 Iris-setosa
1 4.8 3.4 1.9 0.2 Iris-setosa
2 4.7 3.2 1.6 0.2 Iris-setosa
3 4.8 3.1 1.6 0.2 Iris-setosa
4 4.9 2.4 3.3 1.0 Iris-versicolor
@ を使用して、クエリ文字列内でローカル変数を参照します。
var = 4
print(iris.query("(sepalwidth < 2.5) | (sepalwidth > @var)").head(5))
出力:
sepallength sepalwidth petallength petalwidth name
0 5.7 4.4 1.5 0.4 Iris-setosa
1 5.2 4.1 1.5 0.1 Iris-setosa
2 5.5 4.2 1.4 0.2 Iris-setosa
3 4.5 2.3 1.3 0.3 Iris-setosa
4 5.5 2.3 4.0 1.3 Iris-versicolor
query メソッドは、次の構文をサポートしています。
| 構文 | 説明 | |
|---|---|---|
| name | 列名 (@ プレフィックスなし)。@variable を使用して、ローカルの Python 変数を参照します。 |
|
| operator | +、-、*、/、//、%、**、==、!=、<、<=、>、>=、in、not in |
|
| bool | AND:& または and。OR:`|` |
or。 |
| attribute | オブジェクト属性 | |
| index, slice, subscript | スライス操作 |
列を行への変換
explode を使用して、LIST または MAP 型の列を複数の行に展開します。複数行の出力には apply メソッドも使用できます。1つまたは複数の列を同時に展開できます。入力行が出力を生成しない場合 (たとえば、空のリスト)、その行はデフォルトで除外されます。このような行を null 値で保持するには、keep_nulls=True を設定します。
explode を使用した複数行の出力方法の詳細については、「列操作」の「コレクション関連の操作」セクションをご参照ください。
サンプルデータ:
print(df)
# id a b
# 0 1 [a1, b1] [a2, b2, c2]
# 1 2 [c1] [d2, e2]
1つの列を展開し、もう1つはそのまま保持:
print(df[df.id, df.a.explode(), df.b])
出力:
id a b
0 1 a1 [a2, b2, c2]
1 1 b1 [a2, b2, c2]
2 2 c1 [d2, e2]
2つの列を同時に展開:
print(df[df.id, df.a.explode(), df.b.explode()])
出力:
id a b
0 1 a1 a2
1 1 a1 b2
2 1 a1 c2
3 1 b1 a2
4 1 b1 b2
5 1 b1 c2
6 2 c1 d2
7 2 c1 e2
keep_nulls=True — 空の入力を持つ行を保持:
print(df)
# id a
# 0 1 [a1, b1]
# 1 2 []
# keep_nulls なし: 行 2 は削除されます
print(df[df.id, df.a.explode()])
# id a
# 0 1 a1
# 1 1 b1
# keep_nulls=True: 行 2 は null 値で保持されます
print(df[df.id, df.a.explode(keep_nulls=True)])
# id a
# 0 1 a1
# 1 1 b1
# 2 2 None
出力制限
スライス構文または limit メソッドを使用して、返される行数を制限します。
スライス構文:
print(iris[:3].execute())
出力:
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
limit メソッド:
print(iris.limit(3).execute())
出力:
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
MaxCompute SQL バックエンドでは、スライス操作はstartやstepをサポートしておらず、limitのみがサポートされています。スライス操作は Collection オブジェクトにのみ適用され、Sequence オブジェクトには適用されません。