Столбец строки анализа, содержащий дату только с месяцем и годом

Например:

import polars as pl

dates = pl.DataFrame(pl.Series("date", ["2024,2", "2024,12"]))
dates = dates.with_columns(pl.col("date").str.to_date("%Y,%m"))

Это не работает из-за пропущенного дня. Python strptime добавляет день 1:

from time import strptime

strptime("2024,2", "%Y,%m")

Есть ли способ сделать что-то подобное с polars, кроме простого прикрепления к веревочкам в день?

import polars as pl

dates = pl.DataFrame(pl.Series("date", ["2024,2", "2024,12"]))
dates = dates.with_columns((pl.col("date") + ",1").str.to_date(r"%Y,%m,%d"))

Это нормальное решение, но оно выполняет ненужную работу. Итак, лучшее решение, которое я придумал, чтобы не выполнять повторяющуюся работу, это:

import polars as pl

dates = pl.DataFrame(pl.Series("date", ["2024,2", "2024,12"]))
dates = (
    dates.with_columns(
        pl.col("date").str.split(",").list.to_struct(fields=["year", "month"])
    )
    .unnest("date")
    .with_columns(date=pl.date(pl.col("year"), pl.col("month"), 1))
)
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
52
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я думаю, что оба ваших обходных пути действительны, поскольку вашим данным потребуется дополнительная очистка/стандартизация (и это нормально). Вот еще одна альтернатива, которая использует регулярное выражение для заполнения месяцев нулями по мере необходимости:

import polars as pl
import re

def zero_pad(s):
    return re.sub(r",(\d)$", r",0\1", s) # pad number that come after a comma if it is only 1 digit

dates = pl.DataFrame(pl.Series("date", map(zero_pad, ["2024,2", "2024,12"])))
dates = dates.with_columns(pl.col("date").str.to_date("%Y,%m"))

print(dates)

Проблема не в заполнении нулями. Проблема в том, что хроно (ящик даты и времени под капотом) настаивает на том, чтобы день был частью даты.

Dean MacGregor 31.07.2024 05:36
Ответ принят как подходящий

Переход от списка к структуре требует копирования данных, а поскольку строки хранятся как stringview, может быть дешевле просто объединить строки, как в вашем первом решении.

По крайней мере, вы можете пропустить структурирование и отмену вложенности, что также не нужно, используя .list.get(). Вы можете соединить его с оператором-моржом, чтобы он оставался СУХИМ.

dates = dates.with_columns(
    date=pl.date(
        (date_split := pl.col("date").str.split(",")).list.get(0),
        date_split.list.get(1),
        1,
    )
)

Альтернативно вы можете пропустить список, используя .str.split_exact, который заранее возвращает структуру. Если вы это сделаете, вы можете пропустить unnest с помощью .struct[0] и .struct[1], как в

dates.with_columns(
    date=pl.date(
        (datestruct := pl.col("date").str.split_exact(",", 1)).struct[0],
        datestruct.struct[1],
        1,
    )
)

Производительность

Настраивать

df=pl.DataFrame({'dates':pl.date_range(pl.date(1970,1,1), pl.date(2024,7,1), '1mo', eager=True)})
df=df.with_columns(pl.col('dates').dt.strftime("%Y,%m"))

Конкат строк

%%timeit
df.with_columns((pl.col('dates')+",1").str.to_date(r"%Y,%m,%d"))
731 µs ± 6.81 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

через список

%%timeit
dates.with_columns(
    date=pl.date(
        (date_split := pl.col("date").str.split(",")).list.get(0),
        date_split.list.get(1),
        1,
    )
)
1.35 ms ± 6.68 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

через структуру

%%timeit
dates.with_columns(
    date=pl.date(
        (datestruct := pl.col("date").str.split_exact(",", 1)).struct[0],
        datestruct.struct[1],
        1,
    )
)
1.29 ms ± 30.1 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

Заключение

Использование объединения строк намного быстрее, чем разделение строки и использование конструктора даты.

Другие вопросы по теме