CollectionExpr representa um conjunto de dados bidimensional na API PyODPS DataFrame, equivalente a uma tabela do MaxCompute ou a uma planilha. Objetos DataFrame também são objetos CollectionExpr. O CollectionExpr oferece suporte a operações de coluna, filtragem de dados e transformação de dados.
Pré-requisitos
Antes de começar, verifique se você tem:
Uma tabela chamada
pyodps_iris. Para mais informações, consulte a seção "Processamento de dados com DataFrame" em Getting startedUm objeto DataFrame. Para mais informações, consulte a seção "Crie um objeto DataFrame a partir de uma tabela do MaxCompute" em Create a DataFrame object
Obter tipos de colunas
Use o atributo dtypes para obter os tipos de todas as colunas em um CollectionExpr. Esse atributo retorna um Schema type.
print(iris.dtypes)
Saída:
odps.Schema {
sepallength float64
sepalwidth float64
petallength float64
petalwidth float64
name string
}
Selecione, adicionar e exclua colunas
A tabela a seguir indica qual sintaxe usar de acordo com seu objetivo:
|
Objetivo |
Sintaxe recomendada |
Versão do PyODPS |
|
Selecione colunas específicas |
|
Todas as versões |
|
Exclua colunas da seleção |
|
Todas as versões |
|
Adicionar uma coluna calculada |
|
0.7.2+ |
|
Sobrescrever uma coluna existente |
|
0.7.2+ |
|
Exclua uma coluna |
|
0.7.2+ |
|
Atualize condicional de coluna |
|
0.7.2+ |
|
Adicionar uma coluna constante |
|
0.7.12+ |
|
Renomear durante a seleção |
|
Todas as versões |
Selecione colunas
Use expr[columns] para selecione colunas específicas de um CollectionExpr.
print(iris['name', 'sepallength'].head(5))
Saída:
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
Para selecione uma única coluna e retornar uma Collection (em vez de uma Sequence), adicione uma vírgula ao final ou use colchetes duplos:iris[iris.sepallength,]ouiris[[iris.sepallength]]. Sem esses elementos, um objeto Sequence é retornado.
Exclua colunas
Com exclude (todas as versões do PyODPS):
print(iris.exclude('sepallength', 'petallength')[:5].head(5))
Saída:
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
Com del (PyODPS 0.7.2+):
del iris['sepallength']
del iris['petallength']
print(iris[:5].head(5))
Saída:
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
Adicionar colunas
Por sintaxe de atribuição (PyODPS 0.7.2+, recomendado):
iris['sepalwidthplus1'] = iris.sepalwidth + 1
print(iris.head(5))
Saída:
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
Com expr[expr, new_sequence] (todas as versões): Crie uma nova Collection com a coluna adicional anexada. Se a nova coluna tiver o mesmo nome de uma coluna existente, renomeie-a para evitar conflitos.
print(iris[iris, (iris.sepalwidth + 1).rename('sepalwidthplus1')].head(5))
Saída:
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
Adicionar e exclua colunas simultaneamente
Sobrescrever uma coluna existente (PyODPS 0.7.2+):
iris['sepalwidth'] = iris.sepalwidth * 2
print(iris.head(5))
Saída:
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
Combinar exclude com uma nova coluna (todas as versões): Exclua a coluna original e anexa a versão transformada, eliminando a necessidade de renomeação.
print(iris[iris.exclude('sepalwidth'), iris.sepalwidth * 2].head(5))
Saída:
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
Usar select (todas as versões): Funciona de forma semelhante ao exclude com uma nova coluna, mas permite renomear o resultado em uma única etapa usando argumentos nomeados.
print(iris.select('name', sepalwidthminus1=iris.sepalwidth - 1).head(5))
Saída:
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
Por expressão lambda: Passe uma lambda que recebe o resultado da operação anterior como parâmetro. O PyODPS avalia a lambda e substitui as colunas válidas dessa Collection.
print(iris['name', 'petallength'][[lambda x: x.name]].head(5))
Saída:
name
0 Iris-setosa
1 Iris-setosa
2 Iris-setosa
3 Iris-setosa
4 Iris-setosa
Atualize condicional de coluna (PyODPS 0.7.2+): Atualize uma coluna apenas nas linhas que correspondem a uma condição.
iris[iris.sepallength > 5.0, 'sepalwidth'] = iris.sepalwidth * 2
print(iris.head(5))
Saída:
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
Inserir constantes e números aleatórios
Adicionar uma coluna constante
Sintaxe simplificada (PyODPS 0.7.12+, recomendado): Atribua um valor literal diretamente a uma nova coluna.
iris['id'] = 1
print(iris.head(5))
Saída:
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
A sintaxe simplificada não infere automaticamente o tipo de valores nulos. Para adicionar uma coluna nula, use NullScalar com um tipo explícito.
from odps.df import NullScalar
iris['null_col'] = NullScalar('float')
print(iris.head(5))
Saída:
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
Com Scalar (todas as versões): Envolva uma constante com Scalar e especifique o nome da coluna manualmente.
from odps.df import Scalar
print(iris[iris, Scalar(1).rename('id')][:5].head(5))
Saída:
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
Para adicionar uma coluna nula com tipo explícito:
from odps.df import NullScalar
print(iris[iris, NullScalar('float').rename('fid')][:5].head(5))
Saída:
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
Adicionar uma coluna de números aleatórios
Use RandomScalar para anexar uma coluna de valores FLOAT aleatórios no intervalo de 0 a 1, com um valor único por linha. O parâmetro opcional é uma semente aleatória.
from odps.df import RandomScalar
iris[iris, RandomScalar().rename('rand_val')][:5]
Saída:
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
Filtrar dados
Filtre linhas usando operadores padrão, o método filter, o método query ou expressões lambda.
Em expressões de filtro padrão, use¶ AND e|para OR — as palavras-chaveandeordo Python não são suportadas. O métodoqueryaceita ambas as formas.
Filtrar por condição:
print(iris[iris.sepallength > 5].head(5))
Saída:
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))
Saída:
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))
Saída:
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))
Saída:
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
Método filter com múltiplas condições: Passar vários argumentos para filter equivale a combiná-los com &.
print(iris.filter(iris.sepalwidth > 3.5, iris.sepalwidth < 4).head(5))
Saída:
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
Expressão lambda para operações encadeadas:
print(iris[iris.sepalwidth > 3.8]['name', lambda x: x.sepallength + 1].head(5))
Saída:
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
Coluna BOOLEAN como filtro: Quando uma Collection contém uma coluna BOOLEAN, use essa coluna diretamente como condição de filtro.
# Check the schema
print(df.dtypes)
# odps.Schema {
# a boolean
# b int64
# }
# Filter using the boolean column
print(df[df.a])
# a b
# 0 True 1
# 1 True 3
Os exemplos a seguir mostram a diferença entre recuperar uma única coluna e usá-la como filtro:
df[df.a, ] # Retrieve a one-column Collection
df[[df.a]] # Retrieve a one-column Collection
df.select(df.a) # Retrieve a one-column Collection explicitly
df[df.a] # Use column a (BOOLEAN) as a filter condition
df.a # Retrieve a column from a Collection
df['a'] # Retrieve a column from a Collection
Filtrar com query
O método query aceita condições de filtro como uma expressão de string, semelhante ao Pandas. Referencie nomes de colunas diretamente na string; prefixe variáveis locais com @.
print(iris.query("(sepallength < 5) and (petallength > 1.5)").head(5))
Saída:
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
Use @ para referenciar uma variável local dentro de uma string de consulta:
var = 4
print(iris.query("(sepalwidth < 2.5) | (sepalwidth > @var)").head(5))
Saída:
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
O método query suporta a seguinte sintaxe:
|
Sintaxe |
Descrição |
|
|
name |
Nomes de colunas (sem o prefixo |
|
|
operator |
|
|
|
bool |
AND: |
|
|
attribute |
Atributos de objeto |
|
|
index, slice, subscript |
Operações de fatiamento |
Converter uma coluna em linhas
Use explode para expandir uma coluna LIST ou MAP em várias linhas. Também é possível usar o método apply para saída de múltiplas linhas. É possível explodir uma ou mais colunas simultaneamente. Se uma linha de entrada não produzir saída (por exemplo, uma lista vazia), a linha será excluída por padrão. Defina keep_nulls=True para reter essas linhas com valores nulos.
Para mais informações sobre como usar explode para saída de múltiplas linhas, consulte a seção "Operações relacionadas a Collection" em Column operations.
Dados de exemplo:
print(df)
# id a b
# 0 1 [a1, b1] [a2, b2, c2]
# 1 2 [c1] [d2, e2]
Explodir uma coluna e manter outra inalterada:
print(df[df.id, df.a.explode(), df.b])
Saída:
id a b
0 1 a1 [a2, b2, c2]
1 1 b1 [a2, b2, c2]
2 2 c1 [d2, e2]
Explodir duas colunas simultaneamente:
print(df[df.id, df.a.explode(), df.b.explode()])
Saída:
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 — reter linhas com entrada vazia:
print(df)
# id a
# 0 1 [a1, b1]
# 1 2 []
# Without keep_nulls: row 2 is dropped
print(df[df.id, df.a.explode()])
# id a
# 0 1 a1
# 1 1 b1
# With keep_nulls=True: row 2 is retained with a null value
print(df[df.id, df.a.explode(keep_nulls=True)])
# id a
# 0 1 a1
# 1 1 b1
# 2 2 None
Limites de saída
Limite o número de linhas retornadas usando sintaxe de fatiamento ou o método limit.
Sintaxe de fatiamento:
print(iris[:3].execute())
Saída:
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
Método limit:
print(iris.limit(3).execute())
Saída:
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
No backend SQL do MaxCompute, as operações de fatiamento não suportamstartoustep— apenaslimité suportado. As operações de fatiamento aplicam-se somente a objetos Collection, não a objetos Sequence.