Как вставить «for_each» или «map» в середину цепочки методов Polars?Python

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Как вставить «for_each» или «map» в середину цепочки методов Polars?

Сообщение Anonymous »

Я использую несколько фильтров и других приложений для преобразования, включая group_by для фрейма данных Polars, цель состоит в том, чтобы подсчитать количество HTML-тегов в одном столбце на дату для каждого издателя. Вот код:

Код: Выделить всё

120 def contains_html3(mindate, parquet_file = default_file, fieldname = "text"):
121     """ checks if html tags are in field """
122
123
124     html_tags = [
125     "", "", "", "", "", "", "", "", "[*]", "", "",
126     "", "", "", "", "", "", "", "", "", "",
127     "", "", "", "", "", "", "", "", "", "",
128     "", "", "[h4]", "[/h4]", "", "", "", "", "
", "
", "[list]", "[/list]", "[list]", "[/list]",
129     "", "", "", "", "", "", "", "", "", "", "", "",
130     "", "", "", "", "", "", "", "", "", "", "", "",
131     "", "", "", "", "", "", "", "", "",
132     "", "", "", "", "", "", "", "", ""]
133
134     gg = (pl.scan_parquet(parquet_file)
135           .cast({"date": pl.Date})
136           .select("publisher", "date", fieldname)
137           .drop_nulls()
138           .group_by("publisher", "date")
139           .agg(pl.col(fieldname).str.contains_any(html_tags).sum().alias(fieldname))
140           .filter(pl.col(fieldname) >  0)
141           .sort(fieldname, descending = True)).collect()
142
143     return gg
Вот пример вывода для fieldname = "text":

Код: Выделить всё

Out[8]:
shape: (22_925, 3)
┌───────────────────────────┬────────────┬──────┐
│ publisher                 ┆ date       ┆ text │
│ ---                       ┆ ---        ┆ ---  │
│ str                       ┆ date       ┆ u64  │
╞═══════════════════════════╪════════════╪══════╡
│ Kronen Zeitung            ┆ 2024-11-20 ┆ 183  │
│ Kronen Zeitung            ┆ 2024-10-25 ┆ 180  │
│ Kronen Zeitung            ┆ 2024-11-14 ┆ 174  │
│ Kronen Zeitung            ┆ 2024-11-06 ┆ 172  │
│ Kronen Zeitung            ┆ 2024-10-31 ┆ 171  │
│ …                         ┆ …          ┆ …    │
│ The Faroe Islands Podcast ┆ 2020-03-31 ┆ 1    │
│ Sunday Standard           ┆ 2024-07-16 ┆ 1    │
│ Stabroek News             ┆ 2024-08-17 ┆ 1    │
│ CivilNet                  ┆ 2024-09-01 ┆ 1    │
│ The Star                  ┆ 2024-06-23 ┆ 1    │
└───────────────────────────┴────────────┴──────┘

Проблема в том, что вместо передачи одного аргумента fieldname = "text" я хотел бы передать список (например, ["text", "original_text" , «перевод», ...]). Идея заключалась в том, чтобы запустить три нижние строки цепочки для каждого элемента списка. Я мог бы обернуть всю цепочку методов поляров в цикл for, а затем объединить полученные фреймы данных, но есть ли лучший способ? Например, вставить карту, foreach или другую подобную конструкцию после предложения group_by, а затем поляры добавляют новый столбец для каждого имени поля без использования цикла?
Как лучше всего с этим справиться?
РЕДАКТИРОВАТЬ С ПОМОЩЬЮ ВОСПРОИЗВОДИМОГО КОДА
Это создаст кадр данных df и образец вывода tc , который представляет собой столбец text1, но вы заметите, что в кадре данных есть 4 столбца, text1…, поэтому мне нужна статистика html-тегов для каждого столбца.

Код: Выделить всё

#colorscheme orbital dark

import polars as pl
import datetime as dt
from math import sqrt
import random
random.seed(8472)
from functools import reduce

html_tags = [
"", "", "", "", "", "", "", "", "[*]", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "[h4]", "[/h4]", "", "", "", "", "
", "
", "[list]", "[/list]", "[list]", "[/list]",
"", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", ""]

def makeword(alphaLength):
"""Make a dummy name if none provided."""
consonants = "bcdfghjklmnpqrstvwxyz"
vowels = "aeiou"
word = ''.join(random.choice(consonants if i % 2 == 0 else vowels)
for i in range(alphaLength))
return word

def makepara(nwords):
"""Make a paragraph of dummy text."""
words = [makeword(random.randint(3, 10)) for _ in range(nwords)]
tags = random.choices(html_tags, k=3)
parawords = random.choices(tags + words, k=nwords)
para = "  ".join(parawords)
return para

def generate_df_with_tags(rows = 100, numdates = 10, num_publishers = 6):
publishers = [makeword(5) for _ in range(num_publishers)]
datesrange = pl.date_range(start := dt.datetime(2024, 2, 1),
end = start + dt.timedelta(days = numdates - 1),
eager = True)
dates = sorted(random.choices(datesrange, k = rows))
df = pl.DataFrame({
"publisher": random.choices(publishers, k = rows),
"date": dates,
"text1": [makepara(15) for _ in range(rows)],
"text2": [makepara(15) for _ in range(rows)],
"text3": [makepara(15) for _ in range(rows)],
"text4": [makepara(15) for _ in range(rows)]
})
return df

def contains_html_so(parquet_file, fieldname = "text"):
""" checks if html tags are in field """

gg = (pl.scan_parquet(parquet_file)
.select("publisher", "date", fieldname)
.drop_nulls()
.group_by("publisher", "date")
.agg(pl.col(fieldname).str.contains_any(html_tags).sum().alias(fieldname))
.filter(pl.col(fieldname) > 0)
.sort(fieldname, descending = True)).collect()

return gg

if __name__ == "__main__":
df = generate_df_with_tags(100)
df.write_parquet("/tmp/test.parquet")
tc = [contains_html_so("/tmp/test.parquet", fieldname = x) for x in ["text1", "text2", "text3", "text4"]]
tcr = (reduce(lambda x, y: x.join(y, how = "full", on = ["publisher", "date"], coalesce = True), tc)
.with_columns((
pl.col("text1").fill_null(0)
+ pl.col("text2").fill_null(0)
+ pl.col("text3").fill_null(0)
+ pl.col("text4").fill_null(0)).alias("sum")).sort("sum", descending = True))
print(tcr)

Желаемый результат:

Код: Выделить всё

In [59]: %run so_question.py
shape: (45, 7)
┌───────────┬────────────┬───────┬───────┬───────┬───────┬─────┐
│ publisher ┆ date       ┆ text1 ┆ text2 ┆ text3 ┆ text4 ┆ sum │
│ ---       ┆ ---        ┆ ---   ┆ ---   ┆ ---   ┆ ---   ┆ --- │
│ str       ┆ date       ┆ u64   ┆ u64   ┆ u64   ┆ u64   ┆ u64 │
╞═══════════╪════════════╪═══════╪═══════╪═══════╪═══════╪═════╡
│ desob     ┆ 2024-02-10 ┆ 5     ┆ 5     ┆ 5     ┆ 5     ┆ 20  │
│ qopir     ┆ 2024-02-03 ┆ 5     ┆ 5     ┆ 5     ┆ 4     ┆ 19  │
│ jerag     ┆ 2024-02-04 ┆ 5     ┆ 5     ┆ 5     ┆ 4     ┆ 19  │
│ jerag     ┆ 2024-02-07 ┆ 5     ┆ 4     ┆ 5     ┆ 5     ┆ 19  │
│ wopav     ┆ 2024-02-07 ┆ 4     ┆ 5     ┆ 3     ┆ 5     ┆ 17  │
│ …         ┆ …          ┆ …     ┆ …     ┆ …     ┆ …     ┆ …   │
│ jerag     ┆ 2024-02-06 ┆ 1     ┆ null  ┆ 1     ┆ 1     ┆ 3   │
│ desob     ┆ 2024-02-05 ┆ 1     ┆ 1     ┆ null  ┆ 1     ┆ 3   │
│ cufeg     ┆ 2024-02-04 ┆ 1     ┆ 1     ┆ 1     ┆ null  ┆ 3   │
│ cufeg     ┆ 2024-02-05 ┆ 1     ┆ null  ┆ 1     ┆ 1     ┆ 3   │
│ wopav     ┆ 2024-02-06 ┆ null  ┆ 1     ┆ 1     ┆ 1     ┆ 3   │
└───────────┴────────────┴───────┴───────┴───────┴───────┴─────┘
По сути, теги подсчитываются по столбцам ["text1", "text2", "text3", "text4"], затем суммируются, игнорируя нули, и сортируются по убыванию сумма. Присоединение должно осуществляться по издателю и дате, внешнему и объединяющемуся.

Подробнее здесь: https://stackoverflow.com/questions/793 ... thod-chain
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»