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 "", "", "
", "
", "", "", "", "", "", "
", "
- ", "
- ", "
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…text4, поэтому мне нужна статистика html-тегов для каждого столбца.
#colorscheme orbital dark
import polars as pl
import datetime as dt
from math import sqrt
import random
random.seed(8472)
html_tags = [
"", "", "", "", "", "", "", "", "[*]", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "
", "
", "", "", "", "", "", "
", "
- ", "
- ", "
"", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "", "", ""]
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):
cols = ["publisher", "date", "text1", "text2", "text3", "text4"]
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 = "text1")
print(tc)
Подробнее здесь: https://stackoverflow.com/questions/793 ... thod-chain