Анализ числовых данных с разделителем тысяч в полярах

У меня есть файл tsv, содержащий целые числа с разделителями тысяч. Я пытаюсь прочитать его, используя polars==1.6.0, кодировка utf-16.

from io import BytesIO
import polars as pl

data = BytesIO(
"""
Id\tA\tB
1\t537\t2,288
2\t325\t1,047
3\t98\t194
""".encode("utf-16")
)

df = pl.read_csv(data, encoding = "utf-16", separator = "\t")
print(df)

Я не могу понять, как заставить поляры обрабатывать столбец «B» как целое число, а не как строку, и я также не могу найти чистый способ приведения его к целому числу.

shape: (3, 3)
┌────────┬─────┬───────┐
│ Id     ┆ A   ┆ B     │
│ ---    ┆ --- ┆ ---   │
│ i64    ┆ i64 ┆ str   │
╞════════╪═════╪═══════╡
│ 1      ┆ 537 ┆ 2,288 │
│ 2      ┆ 325 ┆ 1,047 │
│ 3      ┆ 98  ┆ 194   │
└────────┴─────┴───────┘

приведение не удается, как и явная передача схемы. Я также пробовал использовать str.strip_chars, и чтобы удалить запятую, вместо этого я использую str.replace_all.

df = df.with_columns(
    pl.col("B").str.strip_chars(",").alias("B_strip_chars"),
    pl.col("B").str.replace_all("[^0-9]", "").alias("B_replace"),
)
print(df)
shape: (3, 5)
┌────────┬─────┬───────┬───────────────┬───────────┐
│ Id     ┆ A   ┆ B     ┆ B_strip_chars ┆ B_replace │
│ ---    ┆ --- ┆ ---   ┆ ---           ┆ ---       │
│ i64    ┆ i64 ┆ str   ┆ str           ┆ str       │
╞════════╪═════╪═══════╪═══════════════╪═══════════╡
│ 1      ┆ 537 ┆ 2,288 ┆ 2,288         ┆ 2288      │
│ 2      ┆ 325 ┆ 1,047 ┆ 1,047         ┆ 1047      │
│ 3      ┆ 98  ┆ 194   ┆ 194           ┆ 194       │
└────────┴─────┴───────┴───────────────┴───────────┘

Кроме того, чтобы это работало в целом, мне нужно убедиться, что read_csv не пытается вывести типы для каких-либо столбцов, чтобы я мог преобразовать их все вручную (любой числовой столбец со значением> 999 будет содержать запятую)

🤔 А знаете ли вы, что...
С Python можно создавать ботов для социальных сетей и мессенджеров.


5
55
2

Ответы:

Решено

Чтобы разрешить использование нескольких разделителей ,, используйте .str.replace_all:

df = df.with_columns(pl.col('B').str.replace_all(",", "").cast(pl.Int64))

что дает для примера данных:

   shape: (3, 3)
┌─────┬─────┬──────┐
│ Id  ┆ A   ┆ B    │
│ --- ┆ --- ┆ ---  │
│ i64 ┆ i64 ┆ i64  │
╞═════╪═════╪══════╡
│ 1   ┆ 537 ┆ 2288 │
│ 2   ┆ 325 ┆ 1047 │
│ 3   ┆ 98  ┆ 194  │
└─────┴─────┴──────┘

Если ваши исходные данные имеют формат utf-16 (или что-то еще, кроме utf-8), то Polars преобразует их в utf-8 через Python. Поскольку это в любом случае должно произойти, возможно, лучше выполнить это преобразование самостоятельно и заменить знаки «,» в середине, чтобы встроенная программа чтения csv поляров анализировала данные как числа в начале read_csv, а не на последующем этапе.

data.seek(0)
pl.read_csv(data.read().decode('utf-16').replace(',','').encode('utf-8'), separator = "\t")

Просто чтобы подчеркнуть, что если ваши исходные данные уже имеют формат utf-8, то использование Python для replace почти наверняка медленнее, чем ответ @user19077881. Делайте это только в том случае, если ваш источник не utf-8, потому что Polars все равно преобразует его в utf-8 в Python. Конечно, если у вас есть столбцы, которые на самом деле должны быть строками с запятыми, это не сработает, потому что они не знают разницы.