<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          最強(qiáng) Pandas 平替 -- Polars

          共 30851字,需瀏覽 62分鐘

           ·

          2024-04-01 11:30

          ab3508ee35f22f3eca455bc57a2e5ce8.webp

          這是「進(jìn)擊的Coder」的第 912  篇技術(shù)分享 來源:Python 編程時(shí)光

          閱讀本文大概需要 9 分鐘。


          Polars 是一個(gè)用于操作結(jié)構(gòu)化數(shù)據(jù)的高性能 DataFrame 庫(kù),可以說是平替 pandas 最有潛質(zhì)的包。Polars 其核心部分是用 Rust 編寫的,但該庫(kù)也提供了 Python 接口。它的主要特點(diǎn)包括:

          • 快速: Polars 是從零開始編寫的,緊密與機(jī)器結(jié)合,沒有外部依賴。

          • I/O: 對(duì)所有常見數(shù)據(jù)存儲(chǔ)層提供一流支持:本地、云存儲(chǔ)和數(shù)據(jù)庫(kù)。

          • 易于使用: 以原始意圖編寫查詢。Polars 在內(nèi)部會(huì)使用其查詢優(yōu)化器確定執(zhí)行最有效的方式。

          • 離線處理: Polars 支持通過其流式 API 進(jìn)行離線數(shù)據(jù)轉(zhuǎn)換。這使您能夠處理結(jié)果,而無需同時(shí)將所有數(shù)據(jù)存儲(chǔ)在內(nèi)存中。

          • 并行處理: Polars 通過在可用的 CPU 核心之間分配工作負(fù)載,充分利用計(jì)算機(jī)性能,而無需額外配置。

          • 矢量化查詢引擎: Polars 使用 Apache Arrow,一種列式數(shù)據(jù)格式,以矢量化方式處理查詢。它使用 SIMD 來優(yōu)化CPU使用。

          User guide: https://pola-rs.github.io/polars/user-guide/
          API reference: https://pola-rs.github.io/polars/py-polars/html/reference/io.html

          介紹

          Polars 的目標(biāo)是提供一個(gè)閃電般快速的 DataFrame 庫(kù),具有以下特點(diǎn):

          • 利用計(jì)算機(jī)上所有可用的核心。

          • 通過優(yōu)化查詢來減少不必要的工作/內(nèi)存分配。

          • 處理比可用 RAM 更大得多的數(shù)據(jù)集。

          • 具有一致且可預(yù)測(cè)的 API。

          • 具有嚴(yán)格的模式(在運(yùn)行查詢之前應(yīng)該知道數(shù)據(jù)類型)。

          Polars 是用 Rust 編寫的,這使得它具有 C/C++ 性能,并允許它完全控制查詢引擎中的性能關(guān)鍵部分。因此,Polars 為此付出了很大的努力:

          • 減少冗余的復(fù)制。

          • 高效地遍歷內(nèi)存緩存。

          • 在并行性中最小化爭(zhēng)用。

          • 以塊處理數(shù)據(jù)。

          • 重用內(nèi)存分配。

          # 1. 基礎(chǔ)

           Series & DataFrames

          Series 是一個(gè)一維數(shù)據(jù)結(jié)構(gòu)。在一個(gè) Series 中,所有元素都具有相同的數(shù)據(jù)類型(例如,整數(shù)、字符串)。下面的片段展示了如何創(chuàng)建一個(gè)簡(jiǎn)單的帶有名稱的 Series 對(duì)象。

                import polars as pl
          import numpy as np

          s = pl.Series("a", [1, 2, 3, 4, 5])
          print(s)
          s = pl.Series("a", [1, 2, 3, 4, 5])
          print(s.min())
          print(s.max())
          s = pl.Series("a", ["polar""bear""arctic""polar fox""polar bear"])
          s2 = s.str.replace("polar""pola")
          print(s2)
          from datetime import date

          start = date(2001, 1, 1)
          stop = date(2001, 1, 9)
          s = pl.date_range(start, stop, interval="2d", eager=True)
          print(s.dt.day())

          DataFrame 是一個(gè)二維數(shù)據(jù)結(jié)構(gòu),由一個(gè)或多個(gè) Series 支持,可以看作是對(duì)一系列(例如列表)Series的抽象。在 DataFrame 上可以執(zhí)行的操作與在 SQL 查詢中執(zhí)行的操作非常相似。您可以進(jìn)行 GROUP BY、JOIN、PIVOT,還可以定義自定義函數(shù)。

                from datetime import datetime

          df = pl.DataFrame(
              {
                  "integer": [12345],
                  "date": [
                      datetime(202211),
                      datetime(202212),
                      datetime(202213),
                      datetime(202214),
                      datetime(202215),
                  ],
                  "float": [4.05.06.07.08.0],
              }
          )

          print(df)
          print(df.head(3))
          print(df.describe())

           Reading & writing

                import polars as pl
          from datetime import datetime

          df = pl.DataFrame(
              {
                  "integer": [123],
                  "date": [
                      datetime(202211),
                      datetime(202212),
                      datetime(202213),
                  ],
                  "float": [4.05.06.0],
              }
          )

          print(df)
          df.write_csv("output.csv")
          df_csv = pl.read_csv("output.csv")
          print(df_csv)
          df_csv = pl.read_csv("output.csv", try_parse_dates=True)
          print(df_csv)

           Expressions

                import polars as pl

          # 創(chuàng)建一個(gè)簡(jiǎn)單的 DataFrame
          data = {'column1': [123],
                  'column2': ['a''b''c']}
          df = pl.DataFrame(data)

          # 使用表達(dá)式進(jìn)行選擇
          selected_df = df.select(['column1'])

          # 使用表達(dá)式進(jìn)行過濾
          filtered_df = df.filter(df['column1'] > 1)
          selected_df
          filtered_df

          # 2. 拼接

                df = pl.DataFrame(
              {
                  "a": np.arange(0, 8),
                  "b": np.random.rand(8),
                  "d": [1, 2.0, np.NaN, np.NaN, 0, -5, -42, None],
              }
          )

          df2 = pl.DataFrame(
              {
                  "x": np.arange(0, 8),
                  "y": ["A""A""A""B""B""C""X""X"],
              }
          )
          joined = df.join(df2, left_on="a", right_on="x")
          print(joined)
          stacked = df.hstack(df2)
          print(stacked)

          # 3. 概念

           Data types

          Polars 完全基于 Arrow 數(shù)據(jù)類型,并由 Arrow 內(nèi)存數(shù)組支持。這使得數(shù)據(jù)處理在緩存效率和跨進(jìn)程通信方面得到良好支持。大多數(shù)數(shù)據(jù)類型都與 Arrow 的實(shí)現(xiàn)完全一致,但有一些例外,如 Utf8(實(shí)際上是 LargeUtf8)、CategoricalObject(支持有限)等。以下是一些數(shù)據(jù)類型:

          分組 類型 詳細(xì)信息
          數(shù)值 Int8 8 位有符號(hào)整數(shù)。

          Int16 16 位有符號(hào)整數(shù)。

          Int32 32 位有符號(hào)整數(shù)。

          Int64 64 位有符號(hào)整數(shù)。

          UInt8 8 位無符號(hào)整數(shù)。

          UInt16 16 位無符號(hào)整數(shù)。

          UInt32 32 位無符號(hào)整數(shù)。

          UInt64 64 位無符號(hào)整數(shù)。

          Float32 32 位浮點(diǎn)數(shù)。

          Float64 64 位浮點(diǎn)數(shù)。
          嵌套 Struct 結(jié)構(gòu)數(shù)組表示為 Vec<Series>,用于在單個(gè)列中打包多個(gè)/異構(gòu)值。

          List 列表數(shù)組包含包含列表值的子數(shù)組和一個(gè)偏移數(shù)組(在內(nèi)部實(shí)際上是 Arrow 的 LargeList)。
          時(shí)間 Date 日期表示,內(nèi)部表示為距離 UNIX 紀(jì)元的天數(shù),由 32 位有符號(hào)整數(shù)編碼。

          Datetime 日期時(shí)間表示,內(nèi)部表示為距離 UNIX 紀(jì)元的微秒數(shù),由 64 位有符號(hào)整數(shù)編碼。

          Duration 表示時(shí)間差的類型,內(nèi)部表示為微秒。通過減去 Date/Datetime 創(chuàng)建。

          Time 時(shí)間表示,內(nèi)部表示為距午夜的納秒數(shù)。
          其他 Boolean 布爾類型,實(shí)際上是按位打包的。

          Utf8 字符串?dāng)?shù)據(jù)(實(shí)際上在內(nèi)部是 Arrow 的 LargeUtf8)。

          Binary 以字節(jié)形式存儲(chǔ)數(shù)據(jù)。

          Object 有限支持的數(shù)據(jù)類型,可以是任何值。

          Categorical 一組字符串的分類編碼。

           Contexts

          Polars 已經(jīng)開發(fā)了自己的領(lǐng)域特定語言(DSL)用于數(shù)據(jù)轉(zhuǎn)換。該語言非常易于使用,允許進(jìn)行復(fù)雜的查詢,同時(shí)保持人類可讀性。該語言的兩個(gè)核心組件是上下文(Contexts)和表達(dá)式(Expressions),我們將在下一部分介紹表達(dá)式。

          正如名稱所示,上下文指的是需要評(píng)估表達(dá)式的上下文。有三個(gè)主要的上下文 [^1^]:

          1. 選擇(Selection): df.select([..]), df.with_columns([..])

          2. 過濾(Filtering): df.filter()

          3. 分組/聚合(Group by / Aggregation): df.group_by(..).agg([..])

                df = pl.DataFrame(
              {
                  "nrs": [123, None, 5],
                  "names": ["foo""ham""spam""egg", None],
                  "random": np.random.rand(5),
                  "groups": ["A""A""B""C""B"],
              }
          )
          print(df)
          # 基于df 進(jìn)行計(jì)算,得到新的表格
          out = df.select(
              pl.sum("nrs"), # nrs的和
              pl.col("names").sort(), # names排序后的結(jié)果
              pl.col("names").first().alias("first name"), # names第一個(gè)值
              (pl.mean("nrs") * 10).alias("10xnrs"), # nrs的均值 * 10
          )
          print(out)
          # 原始df 新增列
          df = df.with_columns(
              pl.sum("nrs").alias("nrs_sum"),
              pl.col("random").count().alias("count"),
          )
          print(df)
          out = df.filter(pl.col("nrs") > 2)
          print(out)
          out = df.group_by("groups").agg(
              pl.sum("nrs"),  # sum nrs by groups
              pl.col("random").count().alias("count"),  # count group members
              # sum random where name != null
              pl.col("random").filter(pl.col("names").is_not_null()).sum().name.suffix("_sum"),
              pl.col("names").reverse().alias("reversed names"),
          )
          print(out)

           Lazy / eager API

          Polars支持兩種操作模式:lazy(延遲)和eager(即時(shí))。在eager API中,查詢會(huì)立即執(zhí)行,而在lazy API中,查詢只有在“需要”時(shí)才會(huì)被評(píng)估。

                !wget https://mirror.coggle.club/dataset/heart.csv
          !head heart.csv
          df = pl.read_csv("heart.csv")
          df_small = df.filter(pl.col("age") > 5)
          df_agg = df_small.group_by("sex").agg(pl.col("chol").mean())
          print(df_agg)
          q = (
              pl.scan_csv("heart.csv")
              .filter(pl.col("age") > 5)
              .group_by("sex")
              .agg(pl.col("chol").mean())
          )
          # 生成了計(jì)算邏輯

          df = q.collect() # 真正計(jì)算
          print(df)

           Streaming API

          https://pola-rs.github.io/polars/user-guide/concepts/streaming/

          Lazy API的另一個(gè)額外好處是它允許以流式方式執(zhí)行查詢。與一次性處理所有數(shù)據(jù)不同,Polars可以按批執(zhí)行查詢,使您能夠處理大于內(nèi)存的數(shù)據(jù)集。

                q = (
              pl.scan_csv("heart.csv")
              .filter(pl.col("age") > 5)
              .group_by("sex")
              .agg(pl.col("chol").mean())
          )

          df = q.collect(streaming=True)
          print(df)

          # 4. 表達(dá)式

           Basic operators

                df = pl.DataFrame(
              {
                  "nrs": [1, 2, 3, None, 5],
                  "names": ["foo""ham""spam""egg", None],
                  "random": np.random.rand(5),
                  "groups": ["A""A""B""C""B"],
              }
          )
          print(df)
          df_numerical = df.select(
              (pl.col("nrs") + 5).alias("nrs + 5"),
              (pl.col("nrs") - 5).alias("nrs - 5"),
              (pl.col("nrs") * pl.col("random")).alias("nrs * random"),
              (pl.col("nrs") / pl.col("random")).alias("nrs / random"),
          )
          print(df_numerical)
          df_logical = df.select(
              (pl.col("nrs") > 1).alias("nrs > 1"),
              (pl.col("random") <= 0.5).alias("random <= .5"),
              (pl.col("nrs") != 1).alias("nrs != 1"),
              (pl.col("nrs") == 1).alias("nrs == 1"),
              ((pl.col("random") <= 0.5) & (pl.col("nrs") > 1)).alias("and_expr"),  # and
              ((pl.col("random") <= 0.5) | (pl.col("nrs") > 1)).alias("or_expr"),  # or
          )
          print(df_logical)

           Column selections

                from datetime import date, datetime

          df = pl.DataFrame(
              {
                  "id": [942],
                  "place": ["Mars""Earth""Saturn"],
                  "date": pl.date_range(date(202211), date(202213), "1d", eager=True),
                  "sales": [33.42142134.144.7],
                  "has_people": [False, True, False],
                  "logged_at": pl.datetime_range(
                      datetime(2022121), datetime(2022121002), "1s", eager=True
                  ),
              }
          ).with_row_count("rn")
          print(df)
          out = df.select(pl.col("*"))

          # Is equivalent to
          out = df.select(pl.all())
          print(out)
          out = df.select(pl.col("*").exclude("logged_at""rn"))
          print(out)
          out = df.select(pl.col("date""logged_at").dt.to_string("%Y-%h-%d"))
          print(out)
          out = df.select(pl.col("^.*(as|sa).*$"))
          print(out)
          out = df.select(pl.col(pl.Int64, pl.UInt32, pl.Boolean).n_unique())
          print(out)
          import polars.selectors as cs
          out = df.select(cs.numeric() - cs.first())
          print(out)
          out = df.select(cs.contains("rn"), cs.matches(".*_.*"))
          print(out)

           Functions

                df = pl.DataFrame(
              {
                  "nrs": [1, 2, 3, None, 5],
                  "names": ["foo""ham""spam""egg""spam"],
                  "random": np.random.rand(5),
                  "groups": ["A""A""B""C""B"],
              }
          )
          print(df)
          df_samename = df.select(pl.col("nrs") + 5)
          print(df_samename)
          df_alias = df.select(
              (pl.col("nrs") + 5).alias("nrs + 5"),
              (pl.col("nrs") - 5).alias("nrs - 5"),
          )
          print(df_alias)
          df_alias = df.select(
              pl.col("names").n_unique().alias("unique"),
              pl.approx_n_unique("names").alias("unique_approx"),
          )
          print(df_alias)
          df_conditional = df.select(
              pl.col("nrs"),
              pl.when(pl.col("nrs") > 2)
              .then(pl.lit(True))
              .otherwise(pl.lit(False))
              .alias("conditional"),
          )
          print(df_conditional)

          # 5. 轉(zhuǎn)換

          類型轉(zhuǎn)換(Casting)將列的底層 DataType 轉(zhuǎn)換為新的數(shù)據(jù)類型。Polars 使用 Arrow 在內(nèi)存中管理數(shù)據(jù),并依賴于 Rust 實(shí)現(xiàn)中的計(jì)算核心 來執(zhí)行轉(zhuǎn)換。類型轉(zhuǎn)換通過 cast() 方法實(shí)現(xiàn)。

          cast 方法包括一個(gè) strict 參數(shù),該參數(shù)確定當(dāng) Polars 遇到無法從源 DataType 轉(zhuǎn)換為目標(biāo) DataType 的值時(shí)的行為。默認(rèn)情況下,strict=True,這意味著 Polars 將引發(fā)錯(cuò)誤,通知用戶轉(zhuǎn)換失敗,并提供無法轉(zhuǎn)換的值的詳細(xì)信息。另一方面,如果 strict=False,無法轉(zhuǎn)換為目標(biāo) DataType 的任何值都將悄悄地轉(zhuǎn)換為 null

                df = pl.DataFrame(
              {
                  "integers": [12345],
                  "big_integers": [11000000231000000410000005],
                  "floats": [4.05.06.07.08.0],
                  "floats_with_decimal": [4.5325.56.57.58.5],
              }
          )

          print(df)
          out = df.select(
              pl.col("integers").cast(pl.Float32).alias("integers_as_floats"),
              pl.col("floats").cast(pl.Int32).alias("floats_as_integers"),
              pl.col("floats_with_decimal")
              .cast(pl.Int32)
              .alias("floats_with_decimal_as_integers"),
          )
          print(out)
          out = df.select(
              pl.col("integers").cast(pl.Int16).alias("integers_smallfootprint"),
              pl.col("floats").cast(pl.Float32).alias("floats_smallfootprint"),
          )
          print(out)
          df = pl.DataFrame(
              {
                  "integers": [12345],
                  "float": [4.05.036.07.08.0],
                  "floats_as_string": ["4.0""5.0""6.0""7.0""8.0"],
              }
          )

          out = df.select(
              pl.col("integers").cast(pl.Utf8),
              pl.col("float").cast(pl.Utf8),
              pl.col("floats_as_string").cast(pl.Float64),
          )
          print(out)
          df = pl.DataFrame(
              {
                  "integers": [-10234],
                  "floats": [0.01.02.03.04.0],
                  "bools": [True, False, True, False, True],
              }
          )

          out = df.select(pl.col("integers").cast(pl.Boolean), pl.col("floats").cast(pl.Boolean))
          print(out)
          from datetime import date, datetime

          df = pl.DataFrame(
              {
                  "date": pl.date_range(date(202211), date(202215), eager=True),
                  "datetime": pl.datetime_range(
                      datetime(202211), datetime(202215), eager=True
                  ),
              }
          )

          out = df.select(pl.col("date").cast(pl.Int64), pl.col("datetime").cast(pl.Int64))
          print(out)

           Strings

                df = pl.DataFrame({"animal": ["Crab""cat and dog""rab$bit", None]})

          out = df.select(
              pl.col("animal").str.len_bytes().alias("byte_count"),
              pl.col("animal").str.len_chars().alias("letter_count"),
          )
          print(out)
          out = df.select(
              pl.col("animal"),
              pl.col("animal").str.contains("cat|bit").alias("regex"),
              pl.col("animal").str.contains("rab$", literal=True).alias("literal"),
              pl.col("animal").str.starts_with("rab").alias("starts_with"),
              pl.col("animal").str.ends_with("dog").alias("ends_with"),
          )
          print(out)

           Aggregation

          https://pola-rs.github.io/polars/user-guide/expressions/aggregation/

                df = pl.read_csv("heart.csv")
          print(df)
          q = (
              df.lazy()
              .group_by("sex")
              .agg(
                  pl.count(),
                  pl.col("cp"),
                  pl.first("caa"),
              )
              .sort("count", descending=True)
              .limit(5)
          )

          df = q.collect()
          print(df)
          q = (
              df.lazy()
              .group_by("sex")
              .agg(
                  (pl.col("cp") == 1).sum().alias("anti"),
                  (pl.col("cp") == 2).sum().alias("pro"),
              )
              .sort("pro", descending=True)
              .limit(5)
          )

          df = q.collect()
          print(df)

          # 6. 缺失值

                df = pl.DataFrame(
              {
                  "value": [1, None],
              },
          )
          print(df)
          null_count_df = df.null_count()
          print(null_count_df)
          df = pl.DataFrame(
              {
                  "col1": [1, 2, 3],
                  "col2": [1, None, 3],
              },
          )
          print(df)
          fill_literal_df = df.with_columns(
              pl.col("col2").fill_null(pl.lit(2)),
          )
          print(fill_literal_df)
          fill_forward_df = df.with_columns(
              pl.col("col2").fill_null(strategy="forward"),
          )
          print(fill_forward_df)
          fill_median_df = df.with_columns(
              pl.col("col2").fill_null(pl.median("col2")),
          )
          print(fill_median_df)
          fill_interpolation_df = df.with_columns(
              pl.col("col2").interpolate(),
          )
          print(fill_interpolation_df)

           Window functions

          https://pola-rs.github.io/polars/user-guide/expressions/window/

                !wget https://cdn.coggle.club/Pokemon.csv
          !head Pokemon.csv
          # then let's load some csv data with information about pokemon
          df = pl.read_csv("Pokemon.csv")
          print(df.head())
          out = df.select(
              "Type 1",
              "Type 2",
              pl.col("Attack").mean().over("Type 1").alias("avg_attack_by_type"),
              pl.col("Defense")
              .mean()
              .over(["Type 1""Type 2"])
              .alias("avg_defense_by_type_combination"),
              pl.col("Attack").mean().alias("avg_attack"),
          )
          print(out)
          filtered = df.filter(pl.col("Type 2") == "Psychic").select(
              "Name",
              "Type 1",
              "Speed",
          )
          print(filtered)
          out = filtered.with_columns(
              pl.col(["Name""Speed"]).sort_by("Speed"descending=True).over("Type 1"),
          )
          print(out)

           Lists and Arrays

                weather = pl.DataFrame(
              {
                  "station": ["Station " + str(x) for x in range(1, 6)],
                  "temperatures": [
                      "20 5 5 E1 7 13 19 9 6 20",
                      "18 8 16 11 23 E2 8 E2 E2 E2 90 70 40",
                      "19 24 E9 16 6 12 10 22",
                      "E2 E0 15 7 8 10 E1 24 17 13 6",
                      "14 8 E0 16 22 24 E1",
                  ],
              }
          )
          print(weather)
          out = weather.with_columns(pl.col("temperatures").str.split(" "))
          print(out)
          out = weather.with_columns(pl.col("temperatures").str.split(" ")).explode(
              "temperatures"
          )
          print(out)
          out = weather.with_columns(pl.col("temperatures").str.split(" ")).with_columns(
              pl.col("temperatures").list.head(3).alias("top3"),
              pl.col("temperatures").list.slice(-3, 3).alias("bottom_3"),
              pl.col("temperatures").list.len().alias("obs"),
          )
          print(out)

          # 7. 變形

           Joins

          策略 描述
          inner 返回兩個(gè)數(shù)據(jù)框中具有匹配鍵的行。左框或右框中的非匹配行將被丟棄。
          left 返回左數(shù)據(jù)框中的所有行,無論是否在右數(shù)據(jù)框中找到匹配項(xiàng)。非匹配行的右列將被填充為null。
          outer 返回左右兩個(gè)數(shù)據(jù)框中的所有行。如果在一個(gè)框中找不到匹配項(xiàng),則從另一個(gè)框中的列將被填充為null。
          cross 返回左框中的所有行與右框中的所有行的笛卡爾積。重復(fù)的行將被保留;左框與右框的交叉連接的表長(zhǎng)度始終為len(A) × len(B)
          asof 在此連接中,匹配是根據(jù)最近的鍵而不是相等的鍵執(zhí)行的左連接。
          semi 返回左框中具有與右框中相同的連接鍵的所有行。
          anti 返回左框中連接鍵在右框中出現(xiàn)的所有行。
                df_customers = pl.DataFrame(
              {
                  "customer_id": [1, 2, 3],
                  "name": ["Alice""Bob""Charlie"],
              }
          )
          print(df_customers)
          df_orders = pl.DataFrame(
              {
                  "order_id": ["a""b""c"],
                  "customer_id": [1, 2, 2],
                  "amount": [100, 200, 300],
              }
          )
          print(df_orders)
          df = df_customers.join(df_orders, on="customer_id", how="inner")
          print(df)

          df = df_customers.join(df_orders, on="customer_id", how="left")
          print(df)

          df = df_customers.join(df_orders, on="customer_id", how="outer")
          print(df)

          df = df_customers.join(df_orders, on="customer_id", how="cross")
          print(df)
          df_cars = pl.DataFrame(
              {
                  "id": ["a""b""c"],
                  "make": ["ford""toyota""bmw"],
              }
          )
          print(df_cars)
          df_repairs = pl.DataFrame(
              {
                  "id": ["c""c"],
                  "cost": [100, 200],
              }
          )
          print(df_repairs)
          df = df_cars.join(df_repairs, on="id", how="inner")
          print(df)

          df = df_cars.join(df_repairs, on="id", how="semi")
          print(df)

          df = df_cars.join(df_repairs, on="id", how="anti")
          print(df)
          df_trades = pl.DataFrame(
              {
                  "time": [
                      datetime(2020, 1, 1, 9, 1, 0),
                      datetime(2020, 1, 1, 9, 1, 0),
                      datetime(2020, 1, 1, 9, 3, 0),
                      datetime(2020, 1, 1, 9, 6, 0),
                  ],
                  "stock": ["A""B""B""C"],
                  "trade": [101, 299, 301, 500],
              }
          )
          print(df_trades)

          df_quotes = pl.DataFrame(
              {
                  "time": [
                      datetime(2020, 1, 1, 9, 0, 0),
                      datetime(2020, 1, 1, 9, 2, 0),
                      datetime(2020, 1, 1, 9, 4, 0),
                      datetime(2020, 1, 1, 9, 6, 0),
                  ],
                  "stock": ["A""B""C""A"],
                  "quote": [100, 300, 501, 102],
              }
          )

          print(df_quotes)
          df_asof_join = df_trades.join_asof(df_quotes, on="time", by="stock")
          print(df_asof_join)
          df_asof_tolerance_join = df_trades.join_asof(
              df_quotes, on="time", by="stock", tolerance="1m"
          )
          print(df_asof_tolerance_join)

           Concatenation

                df_v1 = pl.DataFrame(
              {
                  "a": [1],
                  "b": [3],
              }
          )
          df_v2 = pl.DataFrame(
              {
                  "a": [2],
                  "b": [4],
              }
          )
          df_vertical_concat = pl.concat(
              [
                  df_v1,
                  df_v2,
              ],
              how="vertical",
          )
          print(df_vertical_concat)
          df_h1 = pl.DataFrame(
              {
                  "l1": [1, 2],
                  "l2": [3, 4],
              }
          )
          df_h2 = pl.DataFrame(
              {
                  "r1": [5, 6],
                  "r2": [7, 8],
                  "r3": [9, 10],
              }
          )
          df_horizontal_concat = pl.concat(
              [
                  df_h1,
                  df_h2,
              ],
              how="horizontal",
          )
          print(df_horizontal_concat)

           Pivots

                df = pl.DataFrame(
              {
                  "foo": ["A""A""B""B""C"],
                  "N": [1, 2, 2, 4, 2],
                  "bar": ["k""l""m""n""o"],
              }
          )
          print(df)
          out = df.pivot(index="foo", columns="bar", values="N", aggregate_function="first")
          print(out)
          q = (
              df.lazy()
              .collect()
              .pivot(index="foo", columns="bar", values="N", aggregate_function="first")
              .lazy()
          )
          out = q.collect()
          print(out)

           Melts

                import polars as pl

          df = pl.DataFrame(
              {
                  "A": ["a""b""a"],
                  "B": [135],
                  "C": [101112],
                  "D": [246],
              }
          )
          print(df)
          out = df.melt(id_vars=["A""B"], value_vars=["C""D"])
          print(out)

          本文來源: 網(wǎng)絡(luò)。 僅用于傳遞和分享 更多信息,并不代表本平臺(tái)贊同其觀點(diǎn)和對(duì)其真實(shí)性負(fù)責(zé),版權(quán)歸原作者所有,如有侵權(quán)請(qǐng)聯(lián)系我們刪除。

          瀏覽 57
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  一级全黄60分钟免费看 | 天天干亚洲 | 夜夜嗨AⅤ一区二区三区 | 影音先锋男人资源在线播放 | 亚洲三级久久 |