Polars - 0303 Bağlamlar

Bağlamlar

Polars, verileri dönüştürmek için kendi EtkiAlanına Özgü Dil (DSL - Domain Specific Language) geliştirmiştir. Dilin kullanımı çok kolaydır ve insan tarafından okunabilen karmaşık sorgulara izin verir. Dilin iki temel bileşeni, Bağlamlar ve İfadelerdir (sonraki bölümde ele alacağız).

Adından da anlaşılacağı gibi bir bağlam, bir ifadenin değerlendirilmesi gereken bağlamı ifade eder. Üç ana bağlam vardır. (Bu kılavuzda daha sonra ele alınacak olan ek Liste ve SQL bağlamları vardır. Ancak basit olması için bunları şimdilik kapsam dışında bırakıyoruz. ):

  1. Seçim: df.select([..]), df.with_columns([..])
  2. Filtreleme: df.filter()
  3. Gruplama / Kümeleme: df.groupby(..).agg([..])

Örnekler, aşağıdaki DataFrame üzerinden gerçekleştirilir:

df = pl.DataFrame(
    {
        "nrs": [1, 2, 3, None, 5],
        "names": ["foo", "ham", "spam", "egg", None],
        "random": np.random.rand(5),
        "groups": ["A", "A", "B", "C", "B"],
    }
)
print(df)
shape: (5, 4)
┌──────┬───────┬──────────┬────────┐
│ nrs   names  random    groups │
│ ---   ---    ---       ---    │
│ i64   str    f64       str    │
╞══════╪═══════╪══════════╪════════╡
│ 1     foo    0.154163  A      │
│ 2     ham    0.74005   A      │
│ 3     spam   0.263315  B      │
│ null  egg    0.533739  C      │
│ 5     null   0.014575  B      │
└──────┴───────┴──────────┴────────┘

select

select bağlamı ile seçim yapılırken, ifadeler, sütunlar üzerinden uygulanır. Yani Sütunlar baz alınarak seçim yapılır. Bu bağlamdaki ifadeler, tümü aynı uzunlukta veya 1 birim uzunluğunda olan Serileri (series) üretmelidir. Bu şu demek, select bağlamı sonrası, seçim yapılan veri çerçevesinin uzunluğuna (satır sayısına) eşit yeni seri(ler) üretilir.

DataFrame'in yüksekliğine (satır sayısına) uyması için 1 birim uzunluğunda bir Seri (series) yayınlanacaktır. select bağlamı ile bir seçimin kümeleri, ifade kombinasyonları veya hazır değerleri olan yeni sütunlar üretebileceğini unutmayın.

out = df.select(
    [
        pl.sum("nrs"),
        pl.col("names").sort(),
        pl.col("names").first().alias("first name"),
        (pl.mean("nrs") * 10).alias("10xnrs"),
    ]
)
print(out)
shape: (5, 4)
┌─────┬───────┬────────────┬────────┐
│ nrs ┆ names ┆ first name ┆ 10xnrs │
│ --- ┆ ---   ┆ ---        ┆ ---    │
│ i64 ┆ str   ┆ str        ┆ f64    │
╞═════╪═══════╪════════════╪════════╡
│ 11  ┆ null  ┆ foo        ┆ 27.5   │
│ 11  ┆ egg   ┆ foo        ┆ 27.5   │
│ 11  ┆ foo   ┆ foo        ┆ 27.5   │
│ 11  ┆ ham   ┆ foo        ┆ 27.5   │
│ 11  ┆ spam  ┆ foo        ┆ 27.5   │
└─────┴───────┴────────────┴────────┘

Şimdi kodları satır satır açıklamaya çalışayım;

pl.sum("nrs"),
pl.col("names").sort(),
pl.col("names").first().alias("first name"),
pl.mean("nrs") * 10).alias("10xnrs")

Sorgudan görebileceğiniz gibi, select bağlamı çok güçlüdür ve birbirinden bağımsız (ve paralel olarak) rasgele ifadeler gerçekleştirmenize izin verir.

select ifadesine benzer, with_columns ifadesi de vardır. Temel fark, with_columns bağlamı kullanıldığında veri çerçevesindeki orijinal sütunlar tutulur, yeni sütunlar veri çerçevesine eklenir, select bağlamı kullanıldığında ise orijinal sütunlar tutulmaz, yeni sütunlar eklenir.

df = df.with_columns(
    [
        pl.sum("nrs").alias("nrs_sum"),
        pl.col("random").count().alias("count"),
    ]
)
print(df)
shape: (5, 6)
┌──────┬───────┬──────────┬────────┬─────────┬───────┐
│ nrs  ┆ names ┆ random   ┆ groups ┆ nrs_sum ┆ count │
│ ---  ┆ ---   ┆ ---      ┆ ---    ┆ ---     ┆ ---   │
│ i64  ┆ str   ┆ f64      ┆ str    ┆ i64     ┆ u32   │
╞══════╪═══════╪══════════╪════════╪═════════╪═══════╡
│ 1    ┆ foo   ┆ 0.154163 ┆ A      ┆ 11      ┆ 5     │
│ 2    ┆ ham   ┆ 0.74005  ┆ A      ┆ 11      ┆ 5     │
│ 3    ┆ spam  ┆ 0.263315 ┆ B      ┆ 11      ┆ 5     │
│ null ┆ egg   ┆ 0.533739 ┆ C      ┆ 11      ┆ 5     │
│ 5    ┆ null  ┆ 0.014575 ┆ B      ┆ 11      ┆ 5     │
└──────┴───────┴──────────┴────────┴─────────┴───────┘

Kodları açıklayalım;

 pl.sum("nrs").alias("nrs_sum"),
pl.col("random").count().alias("count")

Filter

filter bağlamında, mevcut veri çerçevesini, Boolean veri türü (True / False) olarak değerlendirilen keyfi ifadeye göre filtrelersiniz.

out = df.filter(pl.col("nrs") > 2)
print(out)
shape: (2, 6)
┌─────┬───────┬──────────┬────────┬─────────┬───────┐
│ nrs ┆ names ┆ random   ┆ groups ┆ nrs_sum ┆ count │
│ --- ┆ ---   ┆ ---      ┆ ---    ┆ ---     ┆ ---   │
│ i64 ┆ str   ┆ f64      ┆ str    ┆ i64     ┆ u32   │
╞═════╪═══════╪══════════╪════════╪═════════╪═══════╡
│ 3   ┆ spam  ┆ 0.263315 ┆ B      ┆ 11      ┆ 5     │
│ 5   ┆ null  ┆ 0.014575 ┆ B      ┆ 11      ┆ 5     │
└─────┴───────┴──────────┴────────┴─────────┴───────┘

Kodları açıklayalım;

df.filter(pl.col("nrs") > 2)

Groupby / Aggregation

Groupby bağlamında, ifadeler gruplar üzerinde çalışır ve bu nedenle farklı uzunlukta sonuçlar verebilir (bir grubun birçok üyesi olabilir).

out = df.groupby("groups").agg(
    [
        pl.sum("nrs"),  # sum nrs by groups
        pl.col("random").count().alias("count"),  # count group members
        # sum random where name != null
        pl.col("random").filter(pl.col("names").is_not_null()).sum().suffix("_sum"),
        pl.col("names").reverse().alias(("reversed names")),
    ]
)
print(out)
shape: (3, 5)
┌────────┬──────┬───────┬────────────┬────────────────┐
 groups  nrs   count  random_sum  reversed names 
 ---     ---   ---    ---         ---            
 str     i64   u32    f64         list[str]      
╞════════╪══════╪═══════╪════════════╪════════════════╡
 B       8     2      0.263315    [null, "spam"] 
 C       null  1      0.533739    ["egg"]        
 A       3     2      0.894213    ["ham", "foo"] 
└────────┴──────┴───────┴────────────┴────────────────┘

Kodları açıklayalım;

df.groupby("groups").agg()
pl.sum("nrs"),  # sum nrs by groups
pl.col("random").count().alias("count"),  # count group members
pl.col("random").filter(pl.col("names").is_not_null()).sum().suffix("_sum"),
pl.col("names").reverse().alias(("reversed names")),

Sonuçtan da görebileceğiniz gibi, tüm ifadeler groupby bağlamı tarafından tanımlanan gruba uygulanır. Standart groupby'nin yanı sıra, groupby_dynamic ve groupby_rolling de groupby bağlamına giriştir.

<< Önceki Bölüm Sonraki Bölüm >>
Veri Yapıları İfadeler