PyODPS DataFrame, büyük veri kümeleri üzerinde çeşitli toplama işlemlerini destekler: yerleşik toplama işlevleri, gruplanmış toplamalar, özel toplamalar (kullanıcı tanımlı toplama işlevleri veya UDAF'ler) ve HyperLogLog tabanlı farklı değer tahmini.
Tüm örneklerde veri kaynağı olarak pyodps_iris tablosu kullanılır:
from odps.df import DataFrame
iris = DataFrame(o.get_table('pyodps_iris'))
Yerleşik toplama işlevleri
Aşağıdaki toplama işlevleri DataFrame sütunlarında kullanılabilir.
| İşlev | Açıklama |
|---|---|
count veya size |
Satır sayısını hesaplar |
unique |
Farklı değerlerin sayısını hesaplar |
min |
En küçük değeri döndürür |
max |
En büyük değeri döndürür |
sum |
Toplamı döndürür |
mean |
Ortalama değeri döndürür |
median |
Medyan değerini döndürür |
quantile(p) |
p-kantili döndürür; yalnızca tamsayılar için doğru sonuç verir |
var |
Varyansı döndürür |
std |
Standart sapmayı döndürür |
moment |
N'inci merkezi momenti veya N'inci momenti döndürür |
skew |
Örnek çarpıklığını döndürür (yansız tahmin) |
kurtosis |
Örnek basıklığını döndürür (yansız tahmin) |
cat |
Dizeleri bir ayırıcı ile birleştirir |
tolist |
Bir sütunu listeye dönüştürerek toplar |
PyODPS DataFrames, hem MaxCompute hem de pandas arka uçlarında toplama işlemleri sırasında null değerleri yoksayar. Bu durum pandas DataFrame davranışından farklıdır ancak SQL semantiğiyle uyumludur.
Örnekler
Tüm sayısal sütunları özetleyin — Sayı, en büyük değer, en küçük değer, ortalama ve standart sapmayı tek seferde almak için describe() yöntemini çağırın:
print(iris.describe())
Çıktı:
type sepal_length sepal_width petal_length petal_width
0 count 150.000000 150.000000 150.000000 150.000000
1 mean 5.843333 3.054000 3.758667 1.198667
2 std 0.828066 0.433594 1.764420 0.763161
3 min 4.300000 2.000000 1.000000 0.100000
4 max 7.900000 4.400000 6.900000 2.500000
Tek bir sütunu toplayın:
iris.sepallength.max()
Çıktı: 7.9
Farklı değerler üzerinden toplayın — Toplama işlevinden önce unique() yöntemini çağırın:
iris.name.unique().cat(sep=',')
Çıktı: u'Iris-setosa,Iris-versicolor,Iris-virginica'
Tüm sütunları toplayın — Tüm sütunlar aynı işlemi destekliyorsa bunu tüm DataFrame'e uygulayın:
iris.exclude('category').mean()
Çıktı:
sepal_length sepal_width petal_length petal_width
1 5.843333 3.054000 3.758667 1.198667
Tüm satırları sayın:
iris.count()
Çıktı: 150
Sonucu günlüklerde görüntülemek için print(iris.count().execute()) komutunu çalıştırın.
Verileri gruplayın ve toplayın
PyODPS DataFrame'de Groupby işlemi böl-uygula-birleştir modelini izler:
Bölme:
groupby()veriyi bir veya daha fazla sütuna göre gruplara böler.Uygulama:
agg()veyaaggregate()her gruba bağımsız olarak bir toplama işlevi uygular.Birleştirme: Sonuçlar tek bir DataFrame'de birleştirilir.
Sonuç, hem gruplanan sütunu hem de toplanan sütunu içerir.
Adlandırılmış toplama
Çıktı sütunu adlarını doğrudan kontrol etmek için agg() yöntemine anahtar sözcük bağımsız değişkenleri iletin. Buna adlandırılmış toplama denir; toplanan sütunların adları üzerinde açık kontrol istediğinizde bunu kullanın:
iris.groupby('name').agg(iris.sepallength.max(), smin=iris.sepallength.min())
Çıktı:
name sepallength_max smin
0 Iris-setosa 5.8 4.3
1 Iris-versicolor 7.0 4.9
2 Iris-virginica 7.9 4.9
Bu örnekte, smin=iris.sepallength.min() ifadesi toplanan sütunun adını smin olarak değiştirir.
Grup başına farklı değerleri sayın
İki eşdeğer yaklaşım mevcuttur. Daha kısa bir yazım için value_counts() yöntemini kullanın:
# Using groupby + agg
iris.groupby('name').agg(count=iris.name.count()).sort('count', ascending=False).head(5)
# Using value_counts (equivalent, more concise)
iris['name'].value_counts().head(5)
Her iki yöntem de aynı çıktıyı üretir:
name count
0 Iris-virginica 50
1 Iris-versicolor 50
2 Iris-setosa 50
Gruptan tek bir sütunu toplayın
Yalnızca o toplanan sütunu almak için groupby() işleminden sonra sütuna adına göre erişin:
iris.groupby('name').petallength.sum()
Çıktı:
petallength_sum
0 73.2
1 213.0
2 277.6
Bu sözdizimini kullanırken o sütun üzerindeki toplama işlevleriyle sınırlısınız. Null olmayan kontrollerini veya diğer ifadeleri uygulamak için bunun yerine agg() yöntemini kullanın:
iris.groupby('name').agg(iris.petallength.notnull().sum())
Çıktı:
name petallength_sum
0 Iris-setosa 50
1 Iris-versicolor 50
2 Iris-virginica 50
Sabit bir değere göre gruplayın
Doğal bir gruplama sütunu olmadan tüm satırları birlikte toplamak için Scalar kullanarak sabit bir değere göre gruplayın:
from odps.df import Scalar
iris.groupby(Scalar(1)).petallength.sum()
Çıktı:
petallength_sum
0 563.8
Özel toplamalar yazın
Bir sütuna kullanıcı tanımlı toplama işlevi (UDAF) uygulamak için agg() veya aggregate() yöntemlerini kullanın. Özel bir toplama sınıfı dört yöntemi uygulamalıdır:
| Yöntem | Açıklama |
|---|---|
buffer() |
Kısmi sonuçları biriktiren değiştirilebilir bir nesne (liste veya sözlük) döndürür. Arabellek boyutu veri miktarıyla birlikte artmamalıdır. |
__call__(buffer, *val) |
Arabelleğe bir değer ekler. |
merge(buffer, pbuffer) |
Kısmi arabelleği (pbuffer) ana arabellekle birleştirir. |
getvalue(buffer) |
Nihai toplanan değeri döndürür. |
Örnek: özel ortalama
class Agg(object):
def buffer(self):
return [0.0, 0]
def __call__(self, buffer, val):
buffer[0] += val
buffer[1] += 1
def merge(self, buffer, pbuffer):
buffer[0] += pbuffer[0]
buffer[1] += pbuffer[1]
def getvalue(self, buffer):
if buffer[1] == 0:
return 0.0
return buffer[0] / buffer[1]
iris.sepalwidth.agg(Agg)
Çıktı: 3.0540000000000007
Kullanım notları
Giriş türünden farklıysa çıktı veri türünü belirtin:
iris.sepalwidth.agg(Agg, 'float')
Groupby ile birleştirin:
iris.groupby('name').sepalwidth.agg(Agg)
Çıktı:
petallength_aggregation
0 3.418
1 2.770
2 2.974
Birden çok sütunu toplayın — odps.df modülünden agg() işlevini kullanın ve bir sütun listesi iletin:
class Agg(object):
def buffer(self):
return [0.0, 0.0]
def __call__(self, buffer, val1, val2):
buffer[0] += val1
buffer[1] += val2
def merge(self, buffer, pbuffer):
buffer[0] += pbuffer[0]
buffer[1] += pbuffer[1]
def getvalue(self, buffer):
if buffer[1] == 0:
return 0.0
return buffer[0] / buffer[1]
from odps.df import agg
to_agg = agg([iris.sepalwidth, ], Agg, rtype='float') # Call a user-defined aggregate function (UDAF) to aggregate data in two columns.
iris.groupby('name').agg(val=to_agg)
Çıktı:
name val
0 Iris-setosa 0.682781
1 Iris-versicolor 0.466644
2 Iris-virginica 0.451427
Mevcut bir MaxCompute UDAF'sini ada göre çağırın — Sınıf yerine UDAF adını dize olarak iletin:
# Single column
iris.groupby('name').agg(iris.sepalwidth.agg('your_func'))
# Multiple columns
to_agg = agg([iris.sepalwidth, ], 'your_func', rtype='float')
iris.groupby('name').agg(to_agg.rename('val'))
Python UDF kısıtlamaları nedeniyle LIST ve DICT türleri özel toplamalar için giriş veya çıkış veri türü olarak kullanılamaz.
HyperLogLog sayma
hll_count bir sütundaki farklı değerlerin sayısını tahmin etmek için HyperLogLog algoritmasını uygular. Kesin bir sayı değil, yaklaşık bir sayı döndürür. Büyük veri kümelerinde kesin sayımlar çok yavaş olduğunda (örneğin benzersiz ziyaretçileri (UV) hızlıca tahmin etmek için) bu yöntemi kullanın.
Aşağıdaki örnek bir pandas DataFrame kullanır. Yerel ortamda çalıştırın. DataWorks'te çalıştırıyorsanız önce üçüncü taraf bir paket aracılığıyla pandas'ı içe aktarın.
from odps.df import DataFrame
import pandas as pd
import numpy as np
df = DataFrame(pd.DataFrame({'a': np.random.randint(100000, size=100000)}))
df.a.hll_count()
Çıktı: 63270
Karşılaştırma amacıyla kesin farklı değer sayısı:
df.a.nunique()
Çıktı: 63250
İki sonuç birbirine yakındır ancak özdeş değildir; hll_count hız karşılığında küçük bir hata payını kabul eder.
Farklı öğeleri saymadan önce dize değerlerini bölmek için splitter parametresini kullanın.