Rumah > pembangunan bahagian belakang > Tutorial Python > Polar mengira persentil

Polar mengira persentil

WBOY
Lepaskan: 2024-02-22 12:30:22
ke hadapan
893 orang telah melayarinya

Polar 计算百分位数

Kandungan soalan

Saya mempunyai bingkai data polar dengan satu lajur yang mengandungi tarikh dan lajur lain yang mengandungi harga, dan saya ingin mengira persentil untuk setiap lajur dalam tetingkap 252 x 3 pemerhatian.

Untuk melakukan ini, saya melakukan ini:

prices = prices.sort(by=["date"])
rank_cols = list(set(prices.columns).difference("date"))

percentiles = (
    prices.sort(by=["date"])
    .set_sorted("date")
    .group_by_dynamic(
        index_column=["date"], every="1i", start_by="window", period="756i"
    )
    .agg(
        [
            (pl.col(col).rank() * 100.0 / pl.col(col).count()).alias(
                f"{col}_percentile"
            )
            for col in rank_cols
        ]
    )
)


Salin selepas log masuk

Tetapi pengecualian yang dilemparkan ialah:

traceback (most recent call last):
  file "<string>", line 6, in <module>
  file "/usr/local/lib/python3.10/site-packages/polars/dataframe/group_by.py", line 1047, in agg
    self.df.lazy()
  file "/usr/local/lib/python3.10/site-packages/polars/lazyframe/frame.py", line 1706, in collect
    return wrap_df(ldf.collect())
polars.exceptions.invalidoperationerror: argument in operation 'group_by_dynamic' is not explicitly sorted

- if your data is already sorted, set the sorted flag with: '.set_sorted()'.
- if your data is not sorted, sort the 'expr/series/column' first.

Salin selepas log masuk

Dalam kod saya telah melakukan seperti yang dicadangkan tetapi pengecualian masih wujud.

Editor:

Membuat beberapa perubahan seperti yang dicadangkan oleh @hericks.

import polars as pl
import pandas as pd
from datetime import datetime, timedelta

# generate 10 dates starting from today
start_date = datetime.now().date()
date_list = [start_date + timedelta(days=i) for i in range(10)]

# generate random prices for each date and column
data = {
    'date': date_list,
    'asset_1': [float(f"{i+1}.{i+2}") for i in range(10)],
    'asset_2': [float(f"{i+2}.{i+3}") for i in range(10)],
    'asset_3': [float(f"{i+3}.{i+4}") for i in range(10)],
}


prices = pl.dataframe(data)

prices = prices.cast({"date": pl.date})


rank_cols = list(set(prices.columns).difference("date"))

percentiles = (
    prices.sort(by=["date"])
    .set_sorted("date")
    .group_by_dynamic(
        index_column="date", every="1i", start_by="window", period="4i"
    )
    .agg(
        [
            (pl.col(col).rank() * 100.0 / pl.col(col).count()).alias(
                f"{col}_percentile"
            )
            for col in rank_cols
        ]
    )
)
Salin selepas log masuk

Sekarang saya faham

pyo3_runtime.panicexception: attempt to divide by zero
Salin selepas log masuk

Sunting 2:

Masalahnya ialah penggunaan tarikh, saya menukar tarikh dengan integer dan kemudian masalah itu diselesaikan. (Juga ditambah untuk mendapatkan daftar pertama dahulu)

import polars as pl


int_list = [i+1 for i in range(6)]

# Generate random prices for each date and column
data = {
    'int_index': int_list,
    'asset_1': [1.1, 3.4, 2.6, 4.8, 7.4, 3.2],
    'asset_2': [4, 7, 8, 3, 4, 5],
    'asset_3': [1, 3, 10, 20, 2, 4],
}


# Convert the Pandas DataFrame to a Polars DataFrame
prices = pl.DataFrame(data)


rank_cols = list(set(prices.columns).difference("int_index"))

percentiles = (
    prices.sort(by="int_index")
    .set_sorted("int_index")
    .group_by_dynamic(
        index_column="int_index", every="1i", start_by="window", period="4i"
    )
    .agg(
        [
            (pl.col(col).rank().first() * 100.0 / pl.col(col).count()).alias(
                f"{col}_percentile"
            )
            for col in rank_cols
        ]
    )
)

Salin selepas log masuk

Sunting 3:

Idea yang diberikan ialah indeks i mengambil nilai pada indeks i, i+1, i+2, i+3 dan mengira pangkat persentil daftar i berkenaan dengan empat nilai ini.

Sebagai contoh, untuk indeks pertama (1) dalam aset_1, contoh (dan tiga daftar seterusnya) ialah:

1.1, 3.4, 2.6, 4.8, jadi peratusan daftar pertama ialah 25

Untuk aset_1, contoh indeks kedua (2) (dan tiga daftar seterusnya) ialah:

3.4, 2.6, 4.8 dan 7.4, jadi persentil ialah 50.


Jawapan Betul


Saya masih agak meneka apakah jawapan yang anda harapkan, tetapi anda mungkin boleh mulakan dengan yang ini

Jadi, mempertimbangkan data contoh anda:

import polars as pl

# generate random prices for each date and column
prices = pl.dataframe({
    'int_index': range(6),
    'asset_1': [1.1, 3.4, 2.6, 4.8, 7.4, 3.2],
    'asset_2': [4, 7, 8, 3, 4, 5],
    'asset_3': [1, 3, 10, 20, 2, 4],
})

┌───────────┬─────────┬─────────┬─────────┐
│ int_index ┆ asset_1 ┆ asset_2 ┆ asset_3 │
│ ---       ┆ ---     ┆ ---     ┆ ---     │
│ i64       ┆ f64     ┆ i64     ┆ i64     │
╞═══════════╪═════════╪═════════╪═════════╡
│ 0         ┆ 1.1     ┆ 4       ┆ 1       │
│ 1         ┆ 3.4     ┆ 7       ┆ 3       │
│ 2         ┆ 2.6     ┆ 8       ┆ 10      │
│ 3         ┆ 4.8     ┆ 3       ┆ 20      │
│ 4         ┆ 7.4     ┆ 4       ┆ 2       │
│ 5         ┆ 3.2     ┆ 5       ┆ 4       │
└───────────┴─────────┴─────────┴─────────┘
Salin selepas log masuk

Gunakan rolling() 创建窗口,然后(与您在问题中所做的相同) - rank().first() 除以 count()name.suffix() untuk menetapkan nama baharu pada lajur:

cols = pl.all().exclude('int_index')

percentiles = (
    prices.sort(by="int_index")
    .rolling(index_column="int_index", period="4i", offset="0i", closed="left")
    .agg((cols.rank().first() * 100 / cols.count()).name.suffix('_percentile'))
)

┌───────────┬────────────────────┬────────────────────┬────────────────────┐
│ int_index ┆ asset_1_percentile ┆ asset_2_percentile ┆ asset_3_percentile │
│ ---       ┆ ---                ┆ ---                ┆ ---                │
│ i64       ┆ f64                ┆ f64                ┆ f64                │
╞═══════════╪════════════════════╪════════════════════╪════════════════════╡
│ 0         ┆ 25.0               ┆ 50.0               ┆ 25.0               │
│ 1         ┆ 50.0               ┆ 75.0               ┆ 50.0               │
│ 2         ┆ 25.0               ┆ 100.0              ┆ 75.0               │
│ 3         ┆ 66.666667          ┆ 33.333333          ┆ 100.0              │
│ 4         ┆ 100.0              ┆ 50.0               ┆ 50.0               │
│ 5         ┆ 100.0              ┆ 100.0              ┆ 100.0              │
└───────────┴────────────────────┴────────────────────┴────────────────────┘
Salin selepas log masuk

Anda juga boleh menyemak kandungan di dalam setiap tetingkap:

(
    prices.sort(by="int_index")
    .rolling(index_column="int_index", period="4i", offset="0i", closed="left")
    .agg(cols)
)
┌───────────┬───────────────────┬─────────────┬───────────────┐
│ int_index ┆ asset_1           ┆ asset_2     ┆ asset_3       │
│ ---       ┆ ---               ┆ ---         ┆ ---           │
│ i64       ┆ list[f64]         ┆ list[i64]   ┆ list[i64]     │
╞═══════════╪═══════════════════╪═════════════╪═══════════════╡
│ 0         ┆ [1.1, 3.4, … 4.8] ┆ [4, 7, … 3] ┆ [1, 3, … 20]  │
│ 1         ┆ [3.4, 2.6, … 7.4] ┆ [7, 8, … 4] ┆ [3, 10, … 2]  │
│ 2         ┆ [2.6, 4.8, … 3.2] ┆ [8, 3, … 5] ┆ [10, 20, … 4] │
│ 3         ┆ [4.8, 7.4, 3.2]   ┆ [3, 4, 5]   ┆ [20, 2, 4]    │
│ 4         ┆ [7.4, 3.2]        ┆ [4, 5]      ┆ [2, 4]        │
│ 5         ┆ [3.2]             ┆ [5]         ┆ [4]           │
└───────────┴───────────────────┴─────────────┴───────────────┘
Salin selepas log masuk

Atas ialah kandungan terperinci Polar mengira persentil. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:stackoverflow.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan