TowardsDataScience 2023 博客中文翻译(二百五十)

原文:TowardsDataScience

协议:CC BY-NC-SA 4.0

Polars: Pandas DataFrame 但更快

原文:towardsdatascience.com/pandas-dataframe-but-much-faster-f475d6be4cd4?source=collection_archive---------1-----------------------#2023-01-03

执行多线程优化的 pandas 操作

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Travis Tang

·

关注 发表在 Towards Data Science ·11 min 阅读·2023 年 1 月 3 日

面对现实吧。Pandas 很慢。当你的数据框有几百万行时,等待一行代码执行一分钟变得非常令人沮丧。你会发现等待的时间比实际分析的时间还要长。

解决这个问题的库有很多。PySpark、Vaex、Modin 和 Dask 是一些例子。

今天,我们来看看 Polars

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Polars 非常快。图片由 Midjourney 提供。

我与 Polars、PySpark、Vaex、Modin 和 Dask 并无任何关联。

Polars 是一个极其快速的数据框库。

Polars 非常快。两个基准测试将 Polars 与其替代品进行了比较,结果显示 Polars 是最快的库之一。

一个基准测试将 Polars 与其替代品进行对比,任务是读取数据并执行各种分析任务。Polars 的表现始终优于其他库。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数值越低,速度越快。请注意,基准测试是由 Polars 发布的,因此可能存在一些偏见。 (Source)

另一个 基准测试 由 H2O.ai 发布,比较了 Polars 与其替代品在 5 个查询中的表现。在这里,输入表的大小为 50GB,包含 10 亿行和 9 列。

Polars 再次证明了其优势。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

根据 H2O 的基准测试,Polars 非常快速。 Source

Polars 快速的原因:并行化

Polars 之所以快速,是因为它使用了并行化和缓存高效算法来加速分析任务。以下是它的策略。

  • 减少冗余的复制

  • 高效遍历内存缓存

  • 最小化并行中的竞争

它是用 Rust 创建的,而不是 Python

Polars 比那些尝试使用 Python 实现并发的库(如 Pandas)要快得多。这是因为 Polars 是用 Rust 编写的,而 Rust 在实现并发方面比 Python 更出色。

Python 在实现并发方面表现不佳的原因是它使用了 全局解释器锁 (GIL),而 Rust 中没有这一特性。GIL 是一个锁,只允许一个线程控制 Python 解释器

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Python 比 Rust 慢的原因。照片由 FLY:D 提供,来源于 Unsplash

这样想:你在一个玩具工厂(处理器)里,有四个工人(处理器中的核心)。

在 Python 的情况下:任何时候,一个工人需要持有钥匙(GIL)才能运行玩具机器(Python 解释器)。他们不能共享机器,一个工人必须在将钥匙传递给另一个工人之前完成玩具的工作。因此,本质上,任何时候只有一个工人可以运行玩具机器。其他三个工人处于闲置状态。

在 Rust 的情况下:任何时候,一个工人不需要持有钥匙才能使用玩具机器*。* 他们可以共享机器,一个工人不必在另一个工人开始使用同一台机器之前完成玩具的工作。因此,本质上,多个工人可以同时使用玩具机器。没有人需要闲置。

它支持惰性执行

惰性执行 意味着表达式不会立即被评估,而是仅在需要时才评估。相比之下,急切执行 立即评估表达式。

因此,Polars 可以进行优化——仅运行所需的部分,忽略不必要的部分。它还可以在运行时并行化这些评估。

另一方面,Pandas 执行时是急切的,导致资源浪费。

你可以通过快进到下面的“懒惰地选择列”和“急切地选择列”部分,来查看急切执行和懒惰执行之间的差异示例。

安装 Polars

安装 Polars 很简单。只需在终端中运行以下命令。(注意 [all] 子句在这里是可选的。)

pip install polars[all]

数据集:纽约市停车票(4200 万行 x 51 列)

为了说明 Polars 的使用,我们将使用一个大型数据集,即 4200 万行 纽约市停车票 来自 Kaggle(它具有 公共领域 许可,所以可以随意使用!)

纽约市财政部收集有关每张纽约市停车票的数据(每年约 1000 万张!)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

纽约市停车。照片由 Scott GummersonUnsplash 提供

完整的数据集有 4200 万行,并分布在 4 个文件中——每年一个文件。接下来的博客中,我们将只使用 一个文件(2013 年至 2014 年)。

为什么我们没有使用全部四个文件?不幸的是,当我尝试将所有四个文件连接在一起时,Polars 崩溃了。

下面的所有代码都在 Kaggle notebook 中执行,该 notebook 拥有:

  • 4 个 CPU 核心

  • 30 GB RAM

使用 Polars 读取数据

Polars 提供 scan_csv 选项。扫描会延迟实际的文件解析,而是返回一个名为 LazyFrame 的懒惰计算持有者。

实际计算发生在调用 collect() 时。

为什么我们要延迟实际解析文件?这样可以让 Polars 生成一个最优的执行计划。例如,当调用 collect 时,Polars 可以跳过加载某些列的过程,如果它们在计算中不需要。

# Scanning in 9 million rows and 51 columns. 
# We ignore any potential errors in the dataset due to encoding / dirty null values.
temp_df = pl.scan_csv("/kaggle/input/nyc-parking-tickets/Parking_Violations_Issued_-_Fiscal_Year_2014__August_2013___June_2014_.csv", 
                      ignore_errors = True)

# Read the data
result_df = temp_df.collect()

# Reading dataset
result_df

# Time taken: 14.1 s ± 3.29 s per loop

你还可以使用其他函数来读取数据,包括:

基于条件过滤行

过滤精确值

你也可以使用 filter 关键字来过滤特定的行。为此,你需要使用 pl.col(['column_name_here']) 函数来指定列名。

# Lazily read (scan) in 9 million rows and 51 columns.
temp_df = pl.scan_csv("/kaggle/input/nyc-parking-tickets/Parking_Violations_Issued_-_Fiscal_Year_2014__August_2013___June_2014_.csv", ignore_errors = True)

# Filtering for rows with the "Registration State" in NY
result_df = temp_df.filter(pl.col(['Registration State'])=="NY")

# Run the filtering using collect.
result_df.collect()

# Time taken: 12.6 s ± 205 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

你可以想象,我们可以使用其他操作符,如>(小于)、<(大于)、>=(大于或等于)、&(与)、|(或)来实现更复杂的条件。

过滤更复杂的条件

你也可以根据更复杂的条件进行过滤。在这里,我使用正则表达式来过滤行。条件是Plate ID必须包含‘a’或‘1’。

# Lazily read (scan) in 9 million rows and 51 columns.
temp_df = pl.scan_csv("/kaggle/input/nyc-parking-tickets/Parking_Violations_Issued_-_Fiscal_Year_2014__August_2013___June_2014_.csv", ignore_errors = True)

# Find all carplates that contain the letter 'a' or '1'. 
result_df = temp_df.filter(pl.col("Plate ID").str.contains(r"[a1]"))

# Run the filter using collect.
result_df.collect()

# Time taken: 12 s ± 176 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

过滤精确值(非常慢的方法)

你也可以使用索引选择行,这对 pandas 用户来说是熟悉的选择数据方式。

为此,你不能使用惰性读取 CSV 的scan_csv函数。相反,你应该选择急切读取 CSV 的open_csv函数。

请注意,这是一种反模式,因为它不允许 Polars 进行并行化。

# Eagerly read in 9 million rows and 51 columns.
# Note that we use read_csv, not scan_csv here.
temp_df = pl.read_csv("/kaggle/input/nyc-parking-tickets/Parking_Violations_Issued_-_Fiscal_Year_2014__August_2013___June_2014_.csv", ignore_errors = True)

# Filtering for rows with the "Registration State" in NY
result_df = temp_df[['Registration State']=="NY"]

# Time taken: 15 s ± 3.72 s per loop (mean ± std. dev. of 7 runs, 1 loop each)

选择列

惰性选择列

你可以使用select关键字选择列。请注意,这里的语法已经不同于常规的 pandas 语法。

# Lazily read (scan) in 9 million rows and 51 columns.
temp_df = pl.scan_csv("/kaggle/input/nyc-parking-tickets/Parking_Violations_Issued_-_Fiscal_Year_2014__August_2013___June_2014_.csv", ignore_errors = True)

# Selecting a particular column called Plate ID. 
# In pandas, this will look like result_df = temp_df['Plate ID']
result_df = temp_df.select(['Plate ID']).collect()

# Run it using the collect()
result_df.collect()

# Time taken: 1.59 s ± 24.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

急切选择列

类似地,你可以使用方括号表示法来选择列。然而,如我在上面的“通过索引过滤”部分所提到的,这是一种反模式。

# Eagerly read in all 9 million rows and 51 columns.
temp_df = pl.read_csv("/kaggle/input/nyc-parking-tickets/Parking_Violations_Issued_-_Fiscal_Year_2014__August_2013___June_2014_.csv", ignore_errors = True)

# Selecting the Plate ID column
result_df = temp_df['Plate ID']

# Time taken: 12.8 s ± 304 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

让我们比较惰性执行和急切执行的速度。惰性执行需要 1.59 秒,而急切执行需要 12.8 秒。7 倍的速度提升是因为 Polars 在惰性执行中读取“Plate ID”列,而在急切执行中需要读取所有列(不仅仅是“Plate ID”)。

创建新列

要创建一个新列,Polars 使用with_columns语法。

使用字符串函数创建列

以下示例中,找到字符串列Plate IDlength并将其命名为plate_id_letter_count

# Lazily read (scan) in 9 million rows and 51 columns.
temp_df = pl.scan_csv("/kaggle/input/nyc-parking-tickets/Parking_Violations_Issued_-_Fiscal_Year_2014__August_2013___June_2014_.csv", ignore_errors = True)

# String functions to find all Plate ID that contain the letter 'a' or '1'
result_df = temp_df\
            .with_column(pl.col("Plate ID").str.lengths().alias("plate_id_letter_count"))\

# Evaluate the string function.
result_df.collect()

# Time taken: 14.8 s ± 5.79 s per loop

使用 lambda 函数创建列

可以在map函数中指定lambda函数,以指定应用于特定列的函数。然后,我们可以使用函数的结果创建一个新列。

# Lazily read (scan) in 9 million rows and 51 columns.
temp_df = pl.scan_csv("/kaggle/input/nyc-parking-tickets/Parking_Violations_Issued_-_Fiscal_Year_2014__August_2013___June_2014_.csv", ignore_errors = True)

# Create a new column called "Clean Violation Code"
# using the formula 10000 + df["Violation Code"]
result_df = temp_df.with_columns([
    pl.col("Violation Code").\
    map(lambda x: x+10000).\
    alias("Clean Violation Code")
])

# Evaluate the function.
result_df.collect()

# Time taken: 13.8 s ± 796 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 

执行聚合

我们还提供了一个groupby和聚合的示例。

# Lazily read (scan) in 9 million rows and 51 columns.
temp_df = pl.scan_csv("/kaggle/input/nyc-parking-tickets/Parking_Violations_Issued_-_Fiscal_Year_2014__August_2013___June_2014_.csv", ignore_errors = True)

# For each vehicle registration state, calculate the number of tikcets 
# and create a list of all violation codes.
result_df = temp_df\
            .groupby("Registration State").agg(
    [
        pl.count(),
        pl.col("Violation Code").list(),

    ]
).sort('Registration State')\
.collect()

result_df

# time taken: 2.3 s ± 29.1 ms per loop

组合多个函数

数据科学家经常需要同时执行多个步骤。我们可以使用 Polars 中的.表示法来实现。

在以下示例中,我们首先使用with_columnIssue Date列从string列替换为datetime列。

然后,我们对Registration State进行groupby。对于每个州,我们找到票据的最早Issue Date

最后,我们按字母顺序对Registration State进行排序。

# Lazily read (scan) in 9 million rows and 51 columns.
temp_df = pl.scan_csv("/kaggle/input/nyc-parking-tickets/Parking_Violations_Issued_-_Fiscal_Year_2014__August_2013___June_2014_.csv", ignore_errors = True)

# Combine multiple steps into one
# Convert "Issue Date" intoa date column, 
# Then group by Registration State and perform some aggregation.
result_df = temp_df\
            .with_column(pl.col("Issue Date").str.strptime(pl.Date, fmt="%m/%d/%Y"))\
            .groupby("Registration State").agg(
                [pl.first("Issue Date")]
              ).sort('Registration State')\

# Run the steps
result_df.collect()

# Took 1.69 s ± 18.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

将两个表合并成一个

如果你有两个存储在两个单独文件中的表,并且你想将它们合并成一个数据帧?使用concat方法。

# Lazily scan two dataframes 
temp_df1 = pl.scan_csv("/kaggle/input/nyc-parking-tickets/Parking_Violations_Issued_-_Fiscal_Year_2014__August_2013___June_2014_.csv", ignore_errors = True)
temp_df2 = pl.scan_csv("/kaggle/input/nyc-parking-tickets/Parking_Violations_Issued_-_Fiscal_Year_2015.csv", ignore_errors = True)

# Concatenating datasets
result_df = pl.concat(
    [
        temp_df1,
        temp_df2,
    ],
    how="vertical",
)

# Reading dataset
result_df.collect()

# Time taken: 

按键连接表

你可能需要将一个表中的信息与另一个表连接。为此,你可以使用join方法。

有多种类型的join,包括熟悉的类型(inner、left、right)以及一些新型的(anti、asof、semi)。更多细节请阅读文档

df_cars = pl.DataFrame(
    {
        "id": ["a", "b", "c"],
        "make": ["ford", "toyota", "bmw"],
    }
)
df_repairs = pl.DataFrame(
    {
        "id": ["c", "c"],
        "cost": [100, 200],
    }
)

df_inner_join = df_cars.join(df_repairs, on="id", how="inner")
print(df_inner_join)
shape: (2, 3)
┌─────┬──────┬──────┐
│ id  ┆ make ┆ cost │
│ ---------  │
│ strstr  ┆ i64  │
╞═════╪══════╪══════╡
│ c   ┆ bmw  ┆ 100  │
├╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌╌┤
│ c   ┆ bmw  ┆ 200  │
└─────┴──────┴──────┘

它与 Vaex 有何不同?

我早期写了一篇关于 Vaex 的帖子,并收到许多关于 Vaex 和 Polars 是否不同的评论。以下是我的一些观察。

  1. Vaex 的语法更类似于 Pandas;Polar 的语法更类似于 R 或 PySpark。

  2. Vaex 具有更多的机器学习和数据可视化 API。Polar 的重点是基础的数据处理(过滤、选择、聚合)。

  3. Vaex 是用 CPP 编写的,而 Polars 是用 Rust 编写的。

根据你的使用案例,你可能会发现 Vaex 或 Polars 更好。例如,在纽约数据集中,我无法使用 Polars 连接所有四个 CSV 文件(它会导致内存不足问题),而我可以用 Vaex 做到这一点。

import polars as pl

# Read four dataframes to form a 42.3M parking ticket datasets
temp_df1 = pl.scan_csv("/kaggle/input/nyc-parking-tickets/Parking_Violations_Issued_-_Fiscal_Year_2014__August_2013___June_2014_.csv", ignore_errors = True)
temp_df2 = pl.scan_csv("/kaggle/input/nyc-parking-tickets/Parking_Violations_Issued_-_Fiscal_Year_2015.csv", ignore_errors = True)
temp_df3 = pl.scan_csv("/kaggle/input/nyc-parking-tickets/Parking_Violations_Issued_-_Fiscal_Year_2017.csv", ignore_errors = True)
temp_df4 = pl.scan_csv("/kaggle/input/nyc-parking-tickets/Parking_Violations_Issued_-_Fiscal_Year_2016.csv", ignore_errors = True)

# Concatenating dataset
result_df = pl.concat(
    [
        temp_df1,
        temp_df2,
        temp_df3,
        temp_df4,
    ],
    how="vertical",
)

# Reading dataset
result_df.collect()

# Could not be run since it causes out-of-memory issue. 
import vaex 

# Read four dataframes to form a 42.3M parking ticket datasets
temp_df1 = vaex.open("/kaggle/input/nyc-parking-tickets/Parking_Violations_Issued_-_Fiscal_Year_2014__August_2013___June_2014_.csv", schema_infer_fraction=1)
temp_df2 = vaex.open("/kaggle/input/nyc-parking-tickets/Parking_Violations_Issued_-_Fiscal_Year_2015.csv", schema_infer_fraction=1)
temp_df3 = vaex.open("/kaggle/input/nyc-parking-tickets/Parking_Violations_Issued_-_Fiscal_Year_2017.csv", schema_infer_fraction=1)
temp_df4 = vaex.open("/kaggle/input/nyc-parking-tickets/Parking_Violations_Issued_-_Fiscal_Year_2016.csv", schema_infer_fraction=1)

# Concatenating dataset
result_df = vaex.concat([
        temp_df1,
        temp_df2,
        temp_df3,
        temp_df4
    ])

# Reading dataset
result_df

# Could be run without out-of-memory problem.

判决:在这种条件下使用 Polars。

你应该使用 Polars?Vaex?PySpark?Dask?以下是我的思考方式:

  • 如果你的数据很庞大,进入了 10GB 以上的“大数据”领域,你可能要考虑使用 PySpark。否则,Polars、Vaex 和 Dask 是可能的选择。

  • 如果你有多台计算机在一个集群中,并且你想在这些计算机之间分配工作负载,使用 Dask。

  • 如果你需要可视化、机器学习和深度学习,使用 Vaex。如果不需要,使用 Polars。

这是一个粗略的指南,因为最终的答案取决于你的使用案例。因此,我鼓励你尝试每一个。在某些情况下,Polars 和 Vaex 可能比 PySpark 更快(当数据集有数百万行时)。在某些情况下,Vaex 可以运行,但 Polars 可能会崩溃(如上面的concat示例)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

超级速度的 pandas。图片由 Midjourney 提供。

我是一名数据科学家,我在LinkedIn和 Medium 分享数据科学技巧。关注我以获取更多类似的技巧。

时间序列的 Pandas

原文:towardsdatascience.com/pandas-for-time-series-c6cb7c0a3680

Python 中的数据处理

本文解释了 pandas 的时间序列方法。让我们像专业人士一样处理时间序列。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 KahEm Chu

·发表于 Towards Data Science ·阅读时间 13 分钟·2023 年 7 月 26 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Aron Visuals 提供,Unsplash 上的照片

自从我作为数据科学家进入职场以来,我处理的大多数数据都是时间序列。好吧,时间序列有很多定义,通常定义为一组在一段时间内收集的数据点。或者用 Python 的方式说,它指的是一个带有日期时间索引的数据集,并且至少有一列数值。

这可以是过去几个月的股票价格,过去几周的大型超市销售数据,甚至是一个患者在几个月内记录的血糖水平。

在本文中,我将展示如何将 pandas 应用于时间序列数据集,以生成的血糖水平记录为例。

有了这些,这篇文章将按如下结构进行:

  1. 日期时间格式处理 — 将日期时间序列转换为所需格式

  2. 将日期时间转换为特定周期 — 将每个数据点转换为特定时间段

  3. 根据条件筛选日期时间序列 — 根据选定时间段筛选数据点

  4. 时间偏移 — 将数据点向下移动特定周期

  5. 重新抽样时间序列 — 根据指定的时间周期对数据点进行分组

  6. 折线图

让我们开始吧!

像往常一样,任何 Python 分析的第一步是导入必要的库。

导入库

import pandas as pd
import random
import numpy as np
from datetime import datetime 

创建数据

接下来,让我们为这个演示生成一个血糖水平记录数据集。

def create_demo_data():

    random.seed(365)
    np.random.seed(365)
    number_of_data_rows = 2160

    # generate list of date
    dates = pd.bdate_range(datetime(2020, 7, 1), freq='4H', periods=number_of_data_rows).tolist()

    # create a dictionary with the date generated and blood sugar level
    data = {'date': dates,
            'blood_sugar_level': np.random.normal(5.5, 1, size=(1, number_of_data_rows))[0]}
    # create dataframe
    df = pd.DataFrame(data)
    df = df.sort_values(by=["date"])
    df = df.set_index(keys="date")
    return df

df = create_demo_data()
print(df.shape)
df.head(10)

使用上述脚本,生成了一个包含 2160 个数据点的数据集,记录了一年,间隔 4 小时。数据点从 2020 年 7 月 1 日开始,到 2021 年 6 月 25 日结束。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

前 10 个数据点。图片来源:作者。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后的 10 个数据点。图片来源:作者。

现在数据准备好了,开始吧!😊

日期时间格式操作

以下是五种可以用来操作日期时间序列的方法。

[pandas.Series.dt.normalize](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.dt.normalize.html) — 将时间转换为午夜 12:00:00。

[pandas.Series.dt.round](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.dt.round.html) — 对数据执行四舍五入操作到指定的频率。

[pandas.Series.dt.floor](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.dt.floor.html) — 对数据执行向下取整操作到指定的频率。

[pandas.Series.dt.ceil](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.dt.ceil.html) — 对数据执行向上取整操作到指定的频率。

[pandas.Series.dt.strftime](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.dt.strftime.html) — 使用指定的 date_format 转换为索引。

舍入时间戳的方法

对于.round.floor.ceil方法,我们需要定义频率来舍入时间。频率必须是固定频率,如‘S’(秒),不能是‘ME’(月末)。

根据作者的尝试与错误,固定频率有 D、H、T/min、S、L/ms、U/us 和 N。查看时间序列频率获取所有频率值。

.round.floor.ceil方法之间的区别将在下面的两个例子中显示。下面的两个例子将使用生成的日期列表,而不是为演示生成的数据框。

第一个例子是将时间戳从 2 小时频率间隔舍入到 6 小时频率间隔。

import pandas as pd
# generate dates at 2-hour frequency
ts = pd.date_range(pd.Timestamp("2023-04-06 12:00"), periods=5, freq='2H')
print("Before normalize\n", ts)
freq = "6H"
ts_norm = ts.normalize()
ts_round = ts.round(freq=freq)
ts_floor = ts.floor(freq=freq)
ts_ceil = ts.ceil(freq=freq)
print("After normalize\n", ts_norm)
print("After round off\n",ts_round)
print("After round off to floor\n",ts_floor)
print("After round off to ceiling\n",ts_ceil)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

脚本输出 1。图片来源:作者。

第二个例子是将时间戳从 3 小时频率间隔舍入到 6 小时频率间隔。

import pandas as pd
# generate dates at 3-hour frequency
ts = pd.date_range(pd.Timestamp("2023-04-06 12:00"), periods=5, freq='3H')
print("Before normalize\n", ts)
freq = "6H"
ts_norm = ts.normalize()
ts_round = ts.round(freq=freq)
ts_floor = ts.floor(freq=freq)
ts_ceil = ts.ceil(freq=freq)
print("After normalize\n", ts_norm)
print("After round off\n",ts_round)
print("After round off to floor\n",ts_floor)
print("After round off to ceiling\n",ts_ceil)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

脚本输出 2。图片来源:作者。

6 小时频率意味着时间将被分割成等长的时间段,每个时间段间隔 6 小时,第一个时间段总是从午夜 00:00:00 开始。一天有 24 小时,因此我们会有 4 个时间段,如下图所示。

第一个时间段将是凌晨 12 点到早上 6 点,然后第二个时间段将是早上 6 点到中午 12 点,以此类推。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

round、floor 和 ceil 方法之间的区别。图片来源:作者。

如上图所示,对于 .floor 方法,它将始终返回时间段的下边界。对于 .ceil 方法,则与 .floor 相反,它将始终返回时间段的上边界。

对于 .round 方法,它将返回该时间段的最近边界,但当距离两个边界相等时,它将返回任意一个。

这就是上述三种方法之间的区别。时间戳的舍入方式将影响后续分析的结果,因此,根据需要的分析选择方法是至关重要的。

要在数据框上应用上述方法,我们需要在方法前加上 .dt

要更改日期,我们可以将日期索引复制为一列。

df['dates'] = df.index
df.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一个包含重复日期列的数据框。图片由作者提供。

数据框的 dtypes 如下所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

在下面的第一个示例中,我们将在 6 小时的频率下对时间戳进行舍入。.dt.normalize 将始终将时间舍入到午夜,因此这里只显示日期。

freq = "6H"
df["ts_norm"] = df.dates.dt.normalize()
df["ts_round"] = df.dates.dt.round(freq=freq)
df["ts_floor"] = df.dates.dt.floor(freq=freq)
df["ts_ceil"] = df.dates.dt.ceil(freq=freq)
df.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

第一个示例与生成的日期列表的两个示例相同,时间戳按小时进行舍入。

在下面的第二个示例中,我们将以“D”频率对日期进行舍入,这意味着时间戳将舍入到最近的一天。

freq = "D"
df["ts_norm"] = df.dates.dt.normalize()
df["ts_round"] = df.dates.dt.round(freq=freq)
df["ts_floor"] = df.dates.dt.floor(freq=freq)
df["ts_ceil"] = df.dates.dt.ceil(freq=freq)
df.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

对于第二个示例,.floor 方法将返回时间段的下边界,即与时间戳相同的一天,而 .ceil 方法将始终返回时间段的上边界,即日期的下一天 除非 时间戳是在午夜 00:00 时。

对于 .round 方法,它仍然会返回时间段的最近边界,但当距离两个边界相等时,它将返回任意一个。

转换 DateTime 格式的方法 — strftime()

通过使用 .strftime() 方法,我们可以将时间戳转换为所需的格式。在下面的示例中,标准的 ISO 格式日期已被转换为 , 格式,这可以通过 strftime() 格式代码‘%B %d, %Y’ 表示。%B 代表的是月份的完整名称。查看所有的 strftime() 格式代码 这里

df["formatted_date"] = df["dates"].dt.strftime('%B %d, %Y')
df.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

转换 DateTime 格式,例如将月份从数字转换为完整名称,可以消除 7 是指月份还是日期的混淆。

将 DateTime 转换为特定的时间段

[pandas.Series.dt.to_period](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.dt.to_period.html) — 转换为特定频率的 PeriodArray/Index。将 DatetimeArray/Index 转换为 PeriodArray/Index。

以下第一个示例将时间戳转换为周。

ts = pd.date_range(pd.Timestamp("2023-04-06 13:00"), periods=5, freq='w')
print("Before \n", ts)
freq = "w"
ts_period = ts.to_period(freq=freq)
print("After \n", ts_period)

如下输出所示,日期时间数组已转换为周期数组,其中列表中的每个元素已从时间戳更改为周。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

以下第二个示例将时间戳转换为月份。

ts = pd.date_range(pd.Timestamp("2023-04-06 13:00"), periods=5, freq='w')
print("Before\n", ts)
freq = "M"
ts_period = ts.to_period(freq=freq)
print("After\n", ts_period)

如下输出所示,日期时间数组已转换为月份数组,其中列表中的每个元素已从时间戳更改为月份。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

现在让我们将其应用于数据框。与之前的示例一样,应用方法到数据框时,需要在 .to_period() 前添加 .dt

df["period"] = df["dates"].dt.to_period(freq="M")
df.head()

日期列中的每个日期时间已被转换为月份。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

使用新的周期列,我们可以创建透视表以获得更多见解。例如,我们可以计算每个月的平均血糖水平。

df_pivot = pd.pivot_table(data=df, index="period", values="blood_sugar_level", aggfunc=np.mean)
df_pivot

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

我们还可以通过周期间计算平均血糖水平,以便进行更详细的监测。

df["week_period"] = df["dates"].dt.to_period(freq="W")
df.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

我们可以计算每周的平均血糖水平,如下所示。如果血糖水平在多周内持续上升,则应采取措施进行控制。

df_pivot_week = pd.pivot_table(data=df, index="week_period", values="blood_sugar_level", aggfunc=np.mean)
df_pivot_week.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

如果我们使用每日数据,几天内血糖水平的上升可能仅是由于丰盛的晚餐,但几周内血糖水平的上升可能表明患者的健康存在风险。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

对于透视表,索引标签和列标签将不会处于同一级别,如上图所示。

为了使索引标签和列标签处于同一级别,需要重置索引,如下所示。

df_pivot_week = df_pivot_week.reset_index()
df_pivot_week.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

基于条件过滤 DateTime 系列

[pandas.Series.at_time](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.at_time.html) — 选择一天中特定时间的值(例如,上午 9:30)。

[pandas.Series.between_time](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.between_time.html) — 选择一天中特定时间段之间的值(例如,上午 9:00–9:30)。

这种方法适用于健康记录的调查,例如每天早晨和睡前的血糖水平。它也可以用于跟踪销售或特定时间段内的航班等应用。

在以下示例中,我们将应用上述两种方法来跟踪上午 8 点和晚上 7 点到 9 点之间的血糖水平记录。

# to check the blood sugar level at every morning 8am
df.at_time('8:00')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

在上面的例子中,仅会显示在早上 8 点记录的记录。

注意: 此方法只能应用于索引为DatetimeIndex的数据框,否则会导致如下面所示的 TypeError。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片。

例如下面的例子中,仅会显示晚上 7 点到 9 点之间的前五条记录。

df.between_time(start_time="19:00", end_time="21:00").head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片。

时间移位

[pandas.Series.shift](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.shift.html) — 移动时间索引,如果可用的话使用索引的频率。

注意: 由于此方法根据时间索引移动数据点,因此索引必须是日期时间索引周期索引

df_pivot

让我们回顾前一节的透视表来演示时间移位方法。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片。

df_pivot.shift(periods=1)

我们可以按照脚本中指定的周期向下移位数据点。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片。

通过将周期更改为-1,我们也可以将数据点向上移位一个周期。例如,数据点已经向上移位一个月,这意味着当前的 7 月数据点是 8 月。

df_pivot.shift(periods=-1)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片。

列名可能会产生歧义,因为它没有反映实际值。为了解决这个问题,我们可以将其与.rename()方法结合,直接重命名时间移位列。

df_shift = df_pivot.shift(periods=1).rename(columns={"blood_sugar_level":"previous month value"})
df_shift

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片。

我们可以将原始数据点与移位后的数据点结合,制作比较表。

df_combine = df_pivot.join(df_shift, how="left")
df_combine

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片。

使用上面的两个系列,我们可以计算血糖水平的变化百分比。

df_combine["pct change"] = (df_combine["previous month value"] - df_combine["blood_sugar_level"])/df_combine["previous month value"]
df_combine

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片。

这很酷。你知道什么更酷吗?我们不需要计算变化百分比,pandas已经为你准备好了方法😊!

df_pivot["pct_change"] = df_pivot.pct_change()
df_pivot

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片。

df_pivot["value_change"] = df_pivot["blood_sugar_level"].diff()
df_pivot

继续前面的例子,现在数据框中有两列。当有多个列时,需要指定在哪一列上进行计算。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图片。

重采样时间序列

[pandas.Series.resample](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.resample.html) — 用于时间序列频率转换和重采样的便捷方法。对象必须具有类似日期时间的索引(DatetimeIndex、PeriodIndex 或 TimedeltaIndex),或者调用者必须将类似日期时间的系列/索引的标签传递给 on/level 关键字参数。

下面的例子使用的是上一节中的df_pivot

df_pivot.resample("Q").mean()

上面的脚本将根据时间段索引重新采样数据框,这意味着它将根据指定的时间段进行分组,在本例中是“Q”或季度,通过该时间段内数据点的均值进行分组。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

下面是另一个以不同时间段重新采样数据点的示例。

df_pivot.resample("Y").mean()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

在这个示例中,数据点将根据指定的时间段进行分组,在本例中是“Y”或年份,通过该时间段内数据点的均值进行分组。我们也可以通过该时间段内数据点的最大值进行分组。

df_pivot.resample("Y").max()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

请注意,计算列如pct_changevalue_change也会被加总,因此现在输出中的计算列不再反映正确的值。

请注意,重新采样要求数据框具有类似 DateTime 或时间段的索引,否则会导致类型错误。我们来看看。

df_wrong_example = df_pivot.reset_index()
df_wrong_example.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

df_wrong_example.resample("Y").sum()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

折线图

[pandas.Series.plot.line](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.plot.line.html) — 将 Series 或 DataFrame 绘制为折线图。

我们可以使用.plot()方法和.plot.line()绘制折线图。

df_pivot["blood_sugar_level"].plot.line()
df_pivot["blood_sugar_level"].plot()

上述两个命令产生相同的结果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

如果你注意到,1 月下有 2021 年,或许如果我们让数据从 2020 年 1 月开始,它也会显示 2020 年?

让我们创建一个数据点从 2020 年开始的数据框。

def create_demo_data():

    random.seed(365)
    np.random.seed(365)
    number_of_data_rows = 55

    # create a month data
    dates = pd.bdate_range(datetime(2020, 1, 1), freq='2W', periods=number_of_data_rows).tolist()

    data = {'date': dates,
            'blood_sugar_level': np.random.normal(5.5, 1, size=(1, number_of_data_rows))[0]}

    df = pd.DataFrame(data)
    df = df.sort_values(by=["date"])
    df = df.set_index(keys="date")
    return df

df = create_demo_data()
print(df.shape)
df.head(10)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

df.plot()

让我们绘制图表!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

是的!所以年份会显示在 1 月下,如果你有从年度第二个月或之后的数据,你可能需要更好的标题以减少观众的混乱。

df_pivot["blood_sugar_level"].plot(title="Blood Sugar Level Record from Jul'20 - Jun'21", xlabel="Date", ylabel="Blood Sugar Level")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供。

最后一点,pandas绘图功能需要安装matplotlib库,否则会导致导入错误。

结论

总之,我们已经涵盖了如何格式化 DateTime 序列,以及如何通过重新采样将时间戳更改为时间段或将其分组到时间段中。我们还涵盖了如何根据条件有效过滤时间序列,并上下移动数据点以获取新见解。最后,我们还介绍了如何快速创建图表以查看时间序列的趋势。

关于pandas时间序列的内容就到这里。我希望你喜欢阅读这篇文章,并希望它能帮助你更好地了解如何应用pandas处理时间序列。谢谢!😊

保持联系

订阅 YouTube

附注

我在 [处理 Python 中的日期] (https://medium.com/towards-data-science/dealing-with-dates-in-python-1b4069a07a0f) 中解释了你可以对 DateTime 变量进行的可能操作。

在 报告自动化技巧与 Python 中,我解释了一些报告自动化的技巧。快来看看吧!

感谢你阅读到最后,祝贺你😊!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Hanny Naibaho 提供,来源于 Unsplash

Pandas & Python 数据科学与数据分析技巧 — 第二部分

原文:towardsdatascience.com/pandas-python-tricks-for-data-science-data-analysis-part-2-dc36460de90d

这是我的 Pandas & Python 技巧的第二部分

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Zoumana Keita

·发表于 Towards Data Science ·阅读时间 5 分钟·2023 年 1 月 17 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源:Andrew NeelUnsplash

介绍

几天前,我分享了一些 Python 和 Pandas 技巧,帮助数据分析师和数据科学家快速学习他们可能不知晓的新有价值概念。这也是我每天在LinkedIn上分享的技巧合集的一部分。

这些技巧的视频系列可以在我的 YouTube 频道上查看。

我的系列中的 3 个技巧

Python

从列表中移除重复项

尝试从列表中移除重复项时,你可能会尝试使用𝗳𝗼𝗿 循环方法。

这样做虽然有效,但在处理非常大的数据时效率不高 ❌。

相反,使用𝘀𝗲𝘁() ✅,它本身不接受重复项。

以下是一个说明 💡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

移除重复项(图片来源:作者)

原始列表中的顺序

使用𝘀𝗲𝘁()来从列表中移除重复项是一个很好的方法。

🚨 但要小心使用,因为它不会❌ 保留原始顺序。仅在不关心列表中元素顺序时使用。

相反,使用𝗱𝗶𝗰𝘁.𝗳𝗿𝗼𝗺𝗸𝗲𝘆𝘀() ✅ 保持原始顺序。

以下是一个说明 💡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

原始顺序由 dict.fromkeys 保持(图片来源:作者)

检查元素是否存在于列表中

#Python 技巧 ✨🐍✨

尝试 𝗰𝗵𝗲𝗰𝗸 𝗶𝗳 𝗮𝗻 𝗶𝘁𝗲𝗺 𝗲𝘅𝗶𝘀𝘁𝘀 𝗶𝗻 𝗮 𝗹𝗶𝘀𝘁 时,你可能会尝试使用𝗳𝗼𝗿 循环和 𝗶𝗳 条件方法。

这样做有效,但处理非常大数据时效率不高 ❌。

相反,使用 𝗶𝗻 ✅ 方法,它本地返回布尔值。

以下是一个示例 💡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

检查元素是否存在于列表中(图像作者)

获取 Python 列表中的 N 个最大和最小值

在 Python 中,可以使用 𝗺𝗮𝘅() 和 𝗺𝗶𝗻() 函数分别找到列表的最大值和最小值。

然而,当涉及到获取 𝗡 𝗹𝗮𝗿𝗴𝗲𝘀𝘁 或 𝘀𝗺𝗮𝗹𝗹𝗲𝘀𝘁 值时,你可能会考虑双向方法:

1️⃣ 按递减或递增顺序对列表进行排序。

2️⃣ 检索 N 个最大或最小值。

好策略,但处理大数据时效率不高 ❌。

✅ 相反,你可以使用 𝗻𝗹𝗮𝗿𝗴𝗲𝘀𝘁 和 𝗻𝘀𝗺𝗮𝗹𝗹𝗲𝘀𝘁 函数来自内置的 Python 模块 𝗵𝗲𝗮𝗽𝗾,它是快速 🚀 和内存高效的 👍。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

𝗻𝗹𝗮𝗿𝗴𝗲𝘀𝘁 和 𝗻𝘀𝗺𝗮𝗹𝗹𝗲𝘀𝘁 函数示例(图像作者)

Pandas

使用同一单元格显示多个数据框

大多数时候,我们倾向于使用不同的笔记本单元格来显示不同的数据框,比如相同数据的 head() 和 tail()。

这是因为在同一单元格中使用它们时,只有最后一个会被显示,之前的所有指令都会被忽略 ❌。

✅ 解决此问题,你可以使用 𝗱𝗶𝘀𝗽𝗹𝗮𝘆() 函数。

以下是一个示例 💡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从同一笔记本单元格中获取多个数据框(图像作者)

描述数值列和分类列

应用 𝗱𝗲𝘀𝗰𝗿𝗶𝗯𝗲() 函数没有参数时,自然只返回与数值列相关的统计数据。

这限制了 🚫 我们对数据集的理解,因为大多数时候我们也处理分类列。

✅ 为了解决这个问题,你可以采取双向方法:

1️⃣ 使用 𝗱𝗲𝘀𝗰𝗿𝗶𝗯𝗲() 对数值列进行描述。

2️⃣ 设置参数 𝗶𝗻𝗰𝗹𝘂𝗱𝗲=[𝗼𝗯𝗷𝗲𝗰𝘁] 以提供有关分类列的信息。

以下是一个示例 💡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

描述 包括分类列(图像作者)

创建新列时避免使用 for 循环

在处理 Pandas 数据框时,从现有列创建新列主要是过程的一部分。

这些列的创建方式会影响整体计算时间的效率 ⏰。

有些人可能会使用循环来生成这些派生列。

然而,这可能不是正确的方法 ❌,因为时间复杂度 📈,特别是在处理大数据时。

✅ 采用向量化方法要好得多。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

向量化与 for 循环的示例

保存 Pandas 列的子集

有时我们只对从原始数据框中保存子集列感兴趣,而不是整个数据。

一种方法是创建一个包含感兴趣列的新数据框。

但是,这种方法增加了另一个复杂性 ❌。

✅ 这个问题可以通过指定 columns 参数来解决。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

获取 Pandas 列的子集(图像作者提供)

将网页上的表格数据转换为 Pandas Dataframe

如果你想从网页 🌐 中提取表格作为 Pandas Dataframes,你可以使用 Pandas 的 𝗿𝗲𝗮𝗱_𝗵𝘁𝗺𝗹() 函数。

✅ 它返回网页上所有表格的列表。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将网页表格转换为 Pandas Dataframe(图像作者提供)

结论

感谢阅读! 🎉 🍾

我希望你觉得这份 Python 和 Pandas 技巧的清单对你有帮助!请继续关注,因为内容将每天更新更多技巧。

此外,如果你喜欢阅读我的故事并希望支持我的写作,可以考虑 成为 Medium 会员。每月 $5 的承诺,你就能解锁 Medium 上的无限故事访问权限。

随时关注我的 MediumTwitterYouTube,或者在 LinkedIn 上打个招呼!讨论 AI、ML、数据科学、NLP 和 MLOps 总是令人愉快的!

Pandas & Python 数据科学与数据分析技巧——第三部分

原文:towardsdatascience.com/pandas-python-tricks-for-data-science-data-analysis-part-3-462d0e952925

这是我 Pandas & Python 技巧系列的第三部分

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Zoumana Keita

·发表于 Towards Data Science ·5 分钟阅读·2023 年 2 月 16 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由 Andrew Neel 提供,来源于 Unsplash

介绍

几天前,我分享了一些 Python 和 Pandas 技巧来帮助数据分析师和数据科学家快速学习他们可能不熟悉的新有价值的概念。这也是我每天在LinkedIn上分享的技巧集合的一部分。

Pandas

根据条件替换数据框中的值

如果你想根据条件替换数据框中的值

✅ 你可以使用 Pandas 内置的 𝗺𝗮𝘀𝗸() 函数。

下面是一个示例 💡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为你的 Pandas 数据框应用颜色

你是否曾经希望仅通过查看你的数据框快速找到一些信息❓

例如:

✨ 每列中哪些值是负数?

✨ 每列的最大值或最小值是多少?

✨ 哪些值低于或高于平均值?

列表还在继续…

查看此类信息的一个很好的方法是使用颜色 🎨

✅ 𝗣𝗮𝗻𝗱𝗮𝘀.𝘀𝘁𝘆𝗹𝗲 是一个内置模块,为你的数据框提供了一个高级样式接口。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这里有一个视频示例!

在 Markdown 中打印 Pandas 数据框

以更易于理解的方式打印你的数据框总是更好。

✅ 一种方法是使用 .𝚝𝚘_𝚖𝚊𝚛𝚔𝚍𝚘𝚠𝚗() 函数将其渲染为 Markdown 格式。

请在评论中告诉我你最喜欢哪一个。

✨ 使用 Markdown ✅ 或不使用 Markdown ❌

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过数据框进行类似 SQL 的查询

Pandas 的强大在数据科学中无法被充分探索💻📊

作为数据分析师或科学家,你可能想要在数据中🔎筛选出相关的见解。

✅ 这可以通过 Pandas 中的内置𝗾𝘂𝗲𝗿𝘆()函数来实现。

它基于布尔表达式运行查询,就像你编写自然语言句子一样! 💬

以下是一个示例 🚀

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将 Scikit Learn 处理转换为 Pandas 数据框

如果你仔细观察 🧐 Scikit learn 预处理模块,你可能会注意到底层函数返回一个 numpy 数组 🔢。

这可能会使得追踪数据中特征的原始名称变得困难。

如果没有额外的代码行来保留这些特征名称,拥有一个 Pandas 🐼 数据框不是很好吗?

✅ 这可以通过 Scikit Learn 的新版本(1.2)的𝘀𝗲𝘁_𝗼𝘂𝘁𝗽𝘂𝘁 API 来实现。

以下是一个示例 💡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从 Datetime 列中提取周期

天、周、月或季度 🗓,…… 每一个都可以根据任务的需要发挥重要作用。

✅ 使用𝘁𝗼_𝗽𝗲𝗿𝗶𝗼𝗱()函数,你可以从日期列中提取这些相关信息。

以下是一个示例 💡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Python

列表中的元素数量

仍然使用循环 🔁 来确定列表中每个项目出现的频率?

也许有一种更好、更优雅的 Pythonic 🐍 方法!

✅ 你可以使用 Python 中的𝗖𝗼𝘂𝗻𝘁𝗲𝗿类来计算列表中元素的数量。

以下是一个示例 💡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从多个列表中合并元素

你在尝试从多个列表中汇总元素吗?

❌ 停止使用𝗳𝗼𝗿循环 🔁 并采用以下方法。

✅ Python 内置的𝘇𝗶𝗽()函数。

以下是一个示例 💡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从聚合元素中创建多个列表

当尝试从多个列表中汇总元素时,最优雅和 Pythonic 的方式是使用内置的𝘇𝗶𝗽()函数。

现在,如果你想反向操作:从那些聚合元素中创建多个列表会怎样❓

❌ 忘记𝗳𝗼𝗿循环 🔁

✅ 只需将𝘇𝗶𝗽()函数与𝗮𝘀𝘁𝗲𝗿𝗶𝘀𝗸 *结合使用

以下是一个示例 💡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我是列表推导式的忠实粉丝

不要像大多数人那样只用 Python 编程,采取快捷且最有效的方法。

想象一下,你想从一个现有列表中创建一个只包含偶数的列表。最明显的想法是使用“for”循环。但最优雅的方法是使用列表推导式,它更紧凑、更简单,也更容易调试。

以下是一个示例 💡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

有了列表推导式,就有了字典推导式

与列表推导式类似,也可以创建字典推导式。它也提供了与列表推导式相同的好处。

假设有一个字典,其中键是索引,值是原始列表中实际的偶数。

以下是一个示例 💡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论

感谢阅读! 🎉 🍾

希望你觉得这份 Python 和 Pandas 技巧列表对你有帮助!请继续关注,因为内容会每天更新更多技巧。

如果你喜欢阅读我的文章并希望支持我的写作,可以考虑 成为 Medium 会员。每月 $5 的订阅费用可以解锁 Medium 上所有故事的无限制访问。

你想请我喝咖啡 ☕️ 吗?→ 点击这里!

欢迎在 MediumTwitterYouTube 上关注我,或者在 LinkedIn 上打个招呼。讨论 AI、ML、数据科学、NLP 和 MLOps 的话题总是很愉快的!

离开之前,请查看此系列的最后两部分:

Pandas 和 Python 数据科学与数据分析技巧 — 第一部分

Pandas 和 Python 数据科学与数据分析技巧 — 第二部分

Pandas 和 Python 数据科学与数据分析技巧——第四部分

原文:towardsdatascience.com/pandas-python-tricks-for-data-science-data-analysis-part-4-67f61f69d62c

这是我 Pandas 和 Python 技巧系列的第四部分

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Zoumana Keita

·发表于 Towards Data Science ·阅读时间 4 分钟·2023 年 3 月 16 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Andrew Neel 提供,来源于 Unsplash

介绍

几天前,我分享了 一些 Python 和 Pandas 技巧,以帮助数据分析师和数据科学家快速学习他们可能不知道的新有价值的概念。这也是我每天在 LinkedIn 上分享的技巧系列的一部分。

Pandas

更改列的数据类型

错误的数据格式是处理真实世界 🌏 数据时常见的挑战。

例如,你可能有一个以字符串形式存储的数值,如“34”而不是 34。

✅ 使用 astype 函数,你可以轻松地将数据从一种类型转换为另一种类型(例如,从字符串到数值)。

以下是一个示例 💡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

检查两个 DataFrame 是否相等

两个具有相同名称的列可能不包含相同的值,而两个具有相同索引的行可能不完全相同。

要知道两个 DataFrame 是否相等,你需要深入检查它们是否具有相同的形状和相同的元素 💡。

这就是 Pandas 𝗲𝗾𝘂𝗮𝗹𝘀() 函数派上用场的地方。

✅ 如果两个 DataFrame 相等,它会返回 True。

❌ 如果它们不相等,它会返回 False。

以下是一个示例 🚀

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Python

使你的 Python 输出更具人类可读性

有时候,有必要超越 Python 提供的默认输出,以使其更易于被人类理解 👩🏻‍💼👩🏽‍💼👨🏻‍💼👨🏽‍💼。

✅ 这可以通过使用 humanize 库来实现。

完整的视频教程在这里可以找到更多示例。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将自然语言转换为数值

自然语言🗣️无处不在🌐,即使在我们的 DataFrames 中也是如此。

这本身并不是一件坏事,因为在执行自然语言处理任务时,这种数据是完美的👍💯。

然而,当尝试进行数值计算时,它们的局限性👎🚫变得很明显。

🛠️✅ 要解决这个问题,你可以使用来自 Python 库𝗻𝘂𝗺𝗲𝗿𝗶𝘇𝗲𝗿的𝗻𝘂𝗺𝗲𝗿𝗶𝘇𝗲()函数。

✨ 它将自然语言表达的数字转换为实际的数值。

下面是一个示例🚀

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

合并多个列表

使用+符号可能是合并🔗列表最常见的方法。

然而,当你需要处理多个列表时,一直输入+符号可能会变得很无聊。

✅ 相反,你可以分别使用来自operatorfunctools模块的addreduce函数。

下面是一个示例🚀

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

合并不同大小的可迭代对象

如果你一直在使用zip()函数,那么你可能已经意识到这个限制:它不能处理不同大小的可迭代对象,这可能导致信息丢失。

🛠️✅ 你可以使用zip函数的亲戚:来自itertools模块的zip_longest()函数来解决这个问题。

不是忽略剩余的项,而是将它们的值替换为None

这很好,但使用fillvalue参数将None替换为有意义的值会更棒。

下面是一个示例🚀

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论

谢谢阅读!🎉 🍾

我希望你觉得这份 Python 和 Pandas 技巧的列表有用!请继续关注这里,因为内容将会每天更新更多技巧。

如果你喜欢阅读我的故事并希望支持我的写作,可以考虑 成为 Medium 会员。每月 5 美元的承诺可以让你无限访问 Medium 上的故事。

你想请我喝咖啡☕️吗?→ 来吧!

欢迎随时关注我在MediumTwitterYouTube,或者在LinkedIn打个招呼。讨论 AI、ML、数据科学、NLP 和 MLOps 的内容总是很愉快的!

在你离开之前,请查看下面本系列的最后两个部分:

Pandas & Python 数据科学与数据分析技巧 — 第一部分

Pandas 与 Python 数据科学与数据分析技巧——第二部分

Pandas 与 Python 数据科学与数据分析技巧——第三部分

Pandas 和 Python 数据科学与数据分析技巧 — 第五部分

原文:towardsdatascience.com/pandas-python-tricks-for-data-science-data-analysis-part-5-8fc987cd82da

这是我的 Pandas 和 Python 技巧的第五部分

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Zoumana Keita

·发布于 Towards Data Science ·6 分钟阅读·2023 年 4 月 10 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Andrew Neel 提供,来源于 Unsplash

介绍

几天前,我分享了一些 Python 和 Pandas 的技巧,帮助数据分析师和数据科学家快速学习他们可能不了解的新有价值的概念。这也是我每天在LinkedIn上分享的技巧集合的一部分。

Pandas

结合 SQL 语句和 Pandas

我的直觉告诉我,超过 80% 的数据科学家在日常数据科学活动中使用 Pandas。

我相信这也是因为它作为更广泛的 Python 生态系统的一部分所提供的好处,使得它对许多人都可以访问。

𝙎𝙌𝙇 怎么样?

尽管不是每个人在日常生活中都使用它(因为并不是每个公司都有必要的 SQL 数据库?),SQL 的性能是不可否认的。此外,它是人类可读的,这使得即使是非技术人员也能轻松理解。

❓如果我们能找到一种方法来 𝙘𝙤𝙢𝙗𝙞𝙣𝙚 𝙩𝙝𝙚 𝙗𝙚𝙣𝙚𝙛𝙞𝙩𝙨 𝙤𝙛 𝙗𝙤𝙩𝙝 𝙋𝙖𝙣𝙙𝙖𝙨 𝙖𝙣𝙙 𝙎𝙌𝙇 语句呢?

✅ 这就是 𝗽𝗮𝗻𝗱𝗮𝘀𝗾𝗹 显得非常有用的地方 🎉🎉🎉

下面是一个说明 💡 你也可以观看完整的视频

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

用另一个 DataFrame 更新给定 DataFrame 的数据

在 Pandas 中,有多种方法来替换缺失值 🧩,从简单的插补到更高级的方法。

但是 … 🚨

有时,你只想使用另一个 DataFrame 中的非 NA 值来替换这些值。

✅ 这可以通过 Pandas 内置的更新函数来实现。

它在执行更新之前,会根据索引和列对齐两个数据框。

一般语法 ⚙️ 如下:

𝗳𝗶𝗿𝘀𝘁_𝗱𝗮𝘁𝗮𝗳𝗿𝗮𝗺𝗲.𝘂𝗽𝗱𝗮𝘁𝗲(𝘀𝗲𝗰𝗼𝗻𝗱_𝗱𝗮𝘁𝗮𝗳𝗿𝗮𝗺𝗲)

✨ 从𝗳𝗶𝗿𝘀𝘁_𝗱𝗮𝘁𝗮𝗳𝗿𝗮𝗺𝗲数据框中的缺失值用𝘀𝗲𝗰𝗼𝗻𝗱_𝗱𝗮𝘁𝗮𝗳𝗿𝗮𝗺𝗲中的非缺失值替换

✨ 𝗼𝘃𝗲𝗿𝘄𝗿𝗶𝘁𝗲=𝗧𝗿𝘂𝗲 会用𝘀𝗲𝗰𝗼𝗻𝗱_𝗱𝗮𝘁𝗮𝗳𝗿𝗮𝗺𝗲的数据覆盖𝗳𝗶𝗿𝘀𝘁_𝗱𝗮𝘁𝗮𝗳𝗿𝗮𝗺𝗲的值,这是默认值。如果𝗼𝘃𝗲𝗿𝘄𝗿𝗶𝘁𝗲=𝗙𝗮𝗹𝘀𝗲,则仅替换缺失值。

这里是一个说明 💡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从非结构化数据到结构化数据

数据预处理充满挑战 🔥

想象一下你有这种格式的候选人信息数据:

‘𝗔𝗱𝗷𝗮 𝗞𝗼𝗻𝗲: 𝗵𝗮𝘀 𝗠𝗮𝘀𝘁𝗲𝗿 𝗶𝗻 𝗦𝘁𝗮𝘁𝗶𝘀𝘁𝗶𝗰𝘀 𝗮𝗻𝗱 𝗶𝘀 𝟮𝟯 𝘆𝗲𝗮𝗿𝘀 𝗼𝗹𝗱’

‘𝗙𝗮𝗻𝘁𝗮 𝗧𝗿𝗮𝗼𝗿𝗲: 𝗵𝗮𝘀 𝗽𝗵𝗱 𝗶𝗻 𝗦𝘁𝗮𝘁𝗶𝘀𝘁𝗶𝗰𝘀 𝗮𝗻𝗱 𝗶𝘀 𝟯𝟬 𝘆𝗲𝗮𝗿𝘀 𝗼𝗹𝗱’

然后,你的任务是为每个候选人生成一个包含以下信息的表格以便进一步分析:

✨ 姓名

✨ 学位和研究领域

✨ 年龄

🚨 执行这样的任务可能令人望而生畏 🤯

✅ 这时,Pandas 中的𝘀𝗿.𝗲𝘅𝘁𝗿𝗮𝗰𝘁()函数可以派上用场!

这是一个强大的文本处理函数,用于从非结构化文本数据中提取结构化信息。

下面是一个说明 💡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 agg()函数进行多重聚合

如果你想在一个或多个列上执行多个聚合函数,如𝘀𝘂𝗺、𝗮𝘃𝗲𝗿𝗮𝗴𝗲、𝗰𝗼𝘂𝗻𝘁等。

✅ 你可以在一行代码中结合使用𝗴𝗿𝗼𝘂𝗽𝗯𝘆()和𝗮𝗴𝗴()函数。

这里是一个场景 🎬 👇🏽

让我们假设这些学生的数据包含以下信息:

✨ 学生的研究领域

✨ 他们的成绩

✨ 毕业年份和每个学生的年龄。

你被要求计算每个研究领域和年份的以下信息:

→ 学生人数

→ 平均成绩

→ 平均年龄

下面是一个解决场景的图像说明 💡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在两个指定时间之间选择观测值

在处理时间序列数据时,你可能需要选择两个指定时间之间的观测值进行进一步分析。

✅ 这可以通过使用𝗯𝗲𝘁𝘄𝗲𝗲𝗻_𝘁𝗶𝗺𝗲()函数快速实现。

下面是一个说明 💡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Python

检查所有元素是否满足某个条件

for 循环和 if 语句的组合并不总是编写 Python 代码时最优雅的方式。

例如,假设你想检查可迭代对象的所有元素是否满足某个条件。

可能会出现两种情况:

1️⃣ 要么使用 for 循环和 if 语句。

或者

2️⃣ 使用**all()**内置函数

下面是一个说明 💡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

检查任何元素是否满足某个条件

类似于前面的情况,如果你想检查可迭代对象中的至少一个元素是否满足某个条件。

✅ 然后使用any() 内置函数,这比使用for 循环和if 语句更优雅。

插图类似于上面的图片。

避免嵌套的 for 循环

当你的程序变得更大、更复杂时,编写嵌套的𝗳𝗼𝗿 循环几乎是不可避免的。

❌ 这也可能使你的代码难以阅读和维护。

✅ 更好的选择是使用内置的𝗽𝗿𝗼𝗱𝘂𝗰𝘁() 函数。

以下是一个插图 💡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

自动处理列表中的索引

想象一下,你需要同时访问列表中的元素及其索引。

一种方法是在 for 循环中手动处理索引。

✅ 相反,你可以使用内置的𝗲𝗻𝘂𝗺𝗲𝗿𝗮𝘁𝗲() 函数。

这样有两个主要好处(我能想到的)。

✨ 首先,它会自动处理索引变量。

✨ 这样可以使代码更具可读性。

以下是一个插图 💡

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论

感谢阅读! 🎉 🍾

希望你觉得这个 Python 和 Pandas 技巧列表对你有帮助!请关注这里,因为内容会每天更新更多技巧。

如果你喜欢阅读我的故事并希望支持我的写作,可以考虑 成为 Medium 会员。每月支付 5 美元,你将解锁 Medium 上无限制的故事访问权限。

想请我喝咖啡 ☕️ 吗? → 请在这里!

欢迎关注我的 MediumTwitterYouTube,或者在 LinkedIn 上打个招呼。讨论 AI、ML、数据科学、NLP 和 MLOps 的内容总是很愉快!

在你离开之前,下面是本系列的最后两个部分:

Pandas 和 Python 数据科学与数据分析技巧 — 第一部分

Pandas 和 Python 数据科学与数据分析技巧 — 第二部分

Pandas 和 Python 数据科学与数据分析技巧 — 第三部分

Pandas 和 Python 数据科学与数据分析技巧 — 第四部分

如何将 Pandas DataFrame 写入 CSV 文件

原文:towardsdatascience.com/pandas-to-csv-aab4ac27c455

利用将 pandas DataFrames 写入 CSV 文件时提供的所有选项

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Giorgos Myrianthous

·发布于 Towards Data Science ·阅读时间 5 分钟·2023 年 1 月 13 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Hello I’m Nik 提供,来源于 Unsplash

在使用 pandas 时,一个非常常见的任务是将 DataFrame 导出到 CSV 文件。

在本文中,我们将演示如何将 pandas DataFrame 写入 CSV 文件。此外,我们还将展示如何使用 pandas API 的各种选项来处理缺失值、日期时间格式、压缩,以及处理 CSV 文件中 DataFrame 时可能需要的其他功能。

现在让我们创建一个示例 DataFrame,我们将在本教程中使用并引用它,以演示将 pandas DataFrame 导出为 CSV 文件的几种不同选项。

from datetime import datetime

import pandas as pd

df = pd.DataFrame(
  [
    (1, 'A', True, datetime(2018, 12, 27), 158, None),
    (2, 'B', False, datetime(2019, 11, 15), 10, 76.3),
    (3, 'A', True, None, 210, 78.1),
    (4, 'F', None, datetime(2022, 10, 5), 679, 54.1),
    (5, 'F', False, datetime(2021, 10, 10), 765, 21.1),
    (6, 'F', True, datetime(2021, 7, 23), 132, 4.5),
    (7, 'C', False, datetime(2017, 4, 5), 45, 5.6),
    (8, 'B', False, datetime(2016, 3, 4), 67, 6.7),
    (9, 'A', True, datetime(2019, 4, 5), 786, 78.1),
    (10, 'C', False, datetime(2023, 1, 1), 78, 89.2),
  ],
  columns=['colA', 'colB', 'colC', 'colD', 'colE', 'colF']
)

>>> df
   colA colB   colC       colD  colE  colF
0     1    A   True 2018-12-27   158   NaN
1     2    B  False 2019-11-15    10  76.3
2     3    A   True        NaT   210  78.1
3     4    F   None 2022-10-05   679  54.1
4     5    F  False 2021-10-10   765  21.1
5     6    F   True 2021-07-23   132   4.5
6     7    C  False 2017-04-05    45   5.6
7     8    B  False 2016-03-04    67   6.7
8     9    A   True 2019-04-05   786  78.1
9    10    C  False 2023-01-01    78  89.2

>>> df.dtypes
colA             int64
colB            object
colC            object
colD    datetime64[ns]
colE             int64
colF           float64
dtype: object

将 pandas DataFrame 导出为 CSV 文件

要将 pandas DataFrame 导出为 csv 文件,你只需调用 pandas.DataFrame.to_csv() 函数并提供输出文件名:

df.to_csv('output_df.csv')

输出

,colA,colB,colC,colD,colE,colF
0,1,A,True,2018-12-27,158,
1,2,B,False,2019-11-15,10,76.3
2,3,A,True,,210,78.1
3,4,F,,2022-10-05,679,54.1
4,5,F,False,2021-10-10,765,21.1
5,6,F,True,2021-07-23,132,4.5
6,7,C,False,2017-04-05,45,5.6
7,8,B,False,2016-03-04,67,6.7
8,9,A,True,2019-04-05,786,78.1
9,10,C,False,2023-01-01,78,89.2

更改默认分隔符

如果你想更改默认分隔符( , ),则需要提供 sep 参数。以下示例将 pandas DataFrame 持久化到一个 CSV 文件中,其中列值将使用制表符分隔:

df.to_csv('output_df.csv', sep='\t')

输出

 colA colB colC colD colE colF
0 1 A True 2018-12-27 158 
1 2 B False 2019-11-15 10 76.3
2 3 A True  210 78.1
3 4 F  2022-10-05 679 54.1
4 5 F False 2021-10-10 765 21.1
5 6 F True 2021-07-23 132 4.5
6 7 C False 2017-04-05 45 5.6
7 8 B False 2016-03-04 67 6.7
8 9 A True 2019-04-05 786 78.1
9 10 C False 2023-01-01 78 89.2

排除索引

在前面的示例中,你可能已经注意到,除了列名和数值外,索引也会被保留。如果你想去掉它,只需提供 index=False 参数:

df.to_csv('output_df.csv', index=False)

输出

colA,colB,colC,colD,colE,colF
1,A,True,2018-12-27,158,
2,B,False,2019-11-15,10,76.3
3,A,True,,210,78.1
4,F,,2022-10-05,679,54.1
5,F,False,2021-10-10,765,21.1
6,F,True,2021-07-23,132,4.5
7,C,False,2017-04-05,45,5.6
8,B,False,2016-03-04,67,6.7
9,A,True,2019-04-05,786,78.1
10,C,False,2023-01-01,78,89.2

移除标题

同样,你可以通过传递 header=False 来去掉标题(即列名)。

df.to_csv('output_df.csv', index=False, header=False)

输出

1,A,True,2018-12-27,158,
2,B,False,2019-11-15,10,76.3
3,A,True,,210,78.1
4,F,,2022-10-05,679,54.1
5,F,False,2021-10-10,765,21.1
6,F,True,2021-07-23,132,4.5
7,C,False,2017-04-05,45,5.6
8,B,False,2016-03-04,67,6.7
9,A,True,2019-04-05,786,78.1
10,C,False,2023-01-01,78,89.2

只写出一部分列

有时,你可能只想导出 DataFrame 对象中的一部分列。你可以通过在 columns 参数中指定所需的列来选择要持久化的列:

df.to_csv('output_df.csv', index=False, header=False)

输出

colA,colD,colF
1,2018-12-27,
2,2019-11-15,76.3
3,,78.1
4,2022-10-05,54.1
5,2021-10-10,21.1
6,2021-07-23,4.5
7,2017-04-05,5.6
8,2016-03-04,6.7
9,2019-04-05,78.1
10,2023-01-01,89.2

指定日期时间对象的格式

在我们的示例 DataFrame 中,列 colD 的类型为 datetime,默认情况下,它将以 YYYY-MM-DD 格式导出。你可以在 date_format 参数中指定所需的日期格式。

df.to_csv('output_df.csv', index=False, date_format='%d/%m/%Y')

输出

colA,colB,colC,colD,colE,colF
1,A,True,27/12/2018,158,
2,B,False,15/11/2019,10,76.3
3,A,True,,210,78.1
4,F,,05/10/2022,679,54.1
5,F,False,10/10/2021,765,21.1
6,F,True,23/07/2021,132,4.5
7,C,False,05/04/2017,45,5.6
8,B,False,04/03/2016,67,6.7
9,A,True,05/04/2019,786,78.1
10,C,False,01/01/2023,78,89.2

如果你有兴趣了解更多关于如何处理 Python 中日期时间对象格式的内容,你可以阅读我最近在 Medium 上的一篇文章。

## 如何更改 Pandas 中的日期时间格式

在 Python 和 pandas 中处理日期时间

towardsdatascience.com

更改 NaN 值写入 CSV 文件的方式

默认情况下,to_csv() 函数会将缺失值导出为空字符。na_rep 参数可以用来指定 NaN 值的所需输出格式:

df.to_csv('output_df.csv', index=False, na_rep='N/A')

输出

colA,colB,colC,colD,colE,colF
1,A,True,2018-12-27,158,N/A
2,B,False,2019-11-15,10,76.3
3,A,True,N/A,210,78.1
4,F,N/A,2022-10-05,679,54.1
5,F,False,2021-10-10,765,21.1
6,F,True,2021-07-23,132,4.5
7,C,False,2017-04-05,45,5.6
8,B,False,2016-03-04,67,6.7
9,A,True,2019-04-05,786,78.1
10,C,False,2023-01-01,78,89.2

其他选项

对于大型 DataFrame,你可能需要将输出压缩为 zip 格式。为此,你可以在 compression 参数中指定所需的压缩策略。

df.to_csv('output_df.csv', index=False, compression='gzip')

其他一些压缩策略包括 'zip''gzip''bz2''zstd''tar'

最后,要更改文件格式编码,你可以利用 encoding 参数:

df.to_csv('output_df.csv', index=False, encoding='utf-8')

最后的思考

总结来说,本文展示了将 pandas DataFrame 写入 CSV 文件时的各种选项。从更改默认分隔符、排除索引、移除标题、仅写入部分列、指定日期时间对象的格式,到更改 NaN 值写入 CSV 文件的方式。

pandas API 提供了多种选项来处理将 DataFrame 持久化到 CSV 文件中的不同场景。这使得它成为一个强大的数据处理和分析工具。根据本文提供的知识,你应该能够轻松而准确地将你的 DataFrame 导出到 CSV 文件中。

成为会员 ,阅读 Medium 上的每个故事。你的会员费用直接支持我和你阅读的其他作者。你还将获得对 Medium 上每个故事的全面访问权限。

[## 使用我的推荐链接加入 Medium — Giorgos Myrianthous

作为 Medium 会员,你的部分会员费用会分配给你阅读的作者,并且你可以全面访问每个故事…

gmyrianthous.medium.com](https://gmyrianthous.medium.com/membership?source=post_page-----aab4ac27c455--------------------------------)

你可能也感兴趣的相关文章

## Python 中的代码图示

创建 Python 云系统架构图

towardsdatascience.com ## *args 和 **kwargs 在 Python 中的使用

讨论位置参数和关键字参数之间的区别以及如何在 Python 中使用 *args 和 **kwargs

towardsdatascience.com

Pandas 与 Polars:语法和速度比较

原文:towardsdatascience.com/pandas-vs-polars-a-syntax-and-speed-comparison-5aa54e27497e

理解 Python 库 Pandas 和 Polars 在数据科学中的主要差异

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Leonie Monigatti

·发表于 Towards Data Science ·阅读时间 7 分钟·2023 年 1 月 11 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供

这篇文章基于收到的评论进行了修订,评论者包括 Jakob Ullmann Dr. Robert Kübler,和 Thiago Jaworski 。感谢你们的反馈!

Pandas 是数据科学领域的一个重要 Python 库。但它最大的问题是对于大数据集的操作可能很慢。Polars 是一个旨在更快处理数据的 Pandas 替代品。

Polars 是一个旨在更快处理数据的 Pandas 替代品。

这篇文章简要介绍了 Polars Python 包,并在语法和速度方面将其与流行的数据科学库 Pandas 进行比较。

· 什么是 Polars,它为什么比 Pandas 更快?

· 基准测试设置

· 开始使用 Polars

· Pandas 和 Polars 的比较

∘ 读取数据

∘ 选择和过滤数据

∘ 创建新列

∘ 分组和聚合

∘ 缺失数据

· 结论

你可以在我的 Kaggle Notebook 中找到与这篇文章相关的代码。

什么是 Polars,它为什么比 Pandas 更快?

根据 Polars 用户指南[1],其目标是“提供一个闪电般快速的 DataFrame 库,利用机器上的所有可用核心。”

与 Polars 相比,Pandas 并不会在你的计算机核心之间原生并行处理。像 Dask 这样的其他工具建立在 Pandas 之上,以尝试并行化它们。相反,Polars 是从头开始设计用于并行化的。虽然它是用 Rust 编写的,但 Polars 也有一个 Python 包,这使它成为 Pandas 的潜在替代品。

Polars 有两种不同的 API:急切 API 和延迟 API。

急切 执行类似于 Pandas。这意味着代码直接运行,结果会立即返回。

另一方面,延迟 执行直到你需要结果时才会运行。因为它避免了运行不必要的代码,所以延迟执行可能比急切执行更高效。

对于延迟执行,你必须以 .lazy() 方法开始操作。然后,你可以编写你想做的代码。最后,你需要运行 .collect() 方法来显示结果。

df.lazy()
  .with_columns([(pl.col("col") * 10).alias("new_col")])
  #...
  .collect()

如果你不运行 .collect() 方法,操作不会立即执行。相反,你会看到执行图。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Polars 延迟执行的示例执行图(图片由作者提供,来源于 Kaggle

基准测试设置

对于基准测试,我们将借用我之前文章中的基准测试设置,该文章比较了不同的文件格式。

## 如何处理 Python 中的大型数据集

CSV、Pickle、Parquet、Feather 和 HDF5 的比较

[towardsdatascience.com

这个基准测试设置使用了一个虚拟数据集,其中包含每种数据类型的一列。为了减少比较时的时间噪声,这个虚拟数据集包含 4,000,000 行,并且几乎达到 1GB ,正如 [2] 中建议的那样。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

基准测试虚拟数据集的开头(图片由作者提供,来源于 Kaggle

接下来,我们将使用 %%timeit -n32 -r4 来计时执行。

开始使用 Polars

要设置 Polars,你只需使用 pip 安装即可。

pip install polars

然后,你可以像使用 Pandas 一样导入 Polars Python 包。

import polars as pl
import pandas as pd

现在,你一切准备就绪!

Pandas 与 Polars 的比较

从表面上看,Pandas 和 Polars(急切 API)在语法方面很相似,因为它们共享主要的构建块:Series 和 DataFrames。

此外,许多 Polars 中的表达式类似于 Pandas 表达式:

# Example expressions that work both with Pandas and Polars
df.head() # Get the first n rows
df.tail() # Get the last n rows
df.unique() # Get unique values of this expression. 

但根据 Polars 用户指南 [1],“如果你的 Polars 代码看起来像 Pandas 代码,它可能会运行,但它可能比应该运行的更慢。”

本节探讨 Polars 包在语法和执行时间上如何与 Pandas 区别:

  • 读取数据

  • 选择与筛选数据

  • 创建新列

  • 分组与聚合

  • 缺失数据

读取数据

在 Polars 中读取 CSV 文件会很熟悉,因为你可以像在 Pandas 中一样使用.read_csv()方法:

# Pandas
pd.read_csv('example.csv')

# Polars
pl.read_csv('example.csv')

下面显示了在 Pandas 和 Polars 中读取样本数据集的执行时间:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Pandas 和 Polars 之间读取时间的对比(图片由作者提供,通过Kaggle

对于我们的样本数据集,读取数据的时间约为Pandas 慢 8 倍于 Polars。

选择与筛选数据

Pandas 和 Polars 之间的第一个主要区别是 Polars 不使用索引[1]。相反,每一行都通过其在 DataFrame 中的整数位置进行索引[1]。

尽管相同的 Pandas 代码可以在 Polars 中运行,但这不是最佳实践。在 Polars 中,你应该使用.select()方法来选择数据。

# Pandas
df[['col1', 'col2']] 

# The above code will run with Polars as well, 
# but the correct way in Polars is:
df.select(pl.col(['col1', 'col2'])) 

下面显示了在 Pandas 和 Polars 中选择数据的执行时间:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Pandas 和 Polars 之间选择时间的对比(图片由作者提供,通过Kaggle

对于我们的样本数据集,使用 Pandas 选择数据的时间约为15 倍长于使用 Polars(约 70.3 µs)。

下方可以看到 Polars 操作与文档建议的语法(使用.select(),左侧)和 Pandas 语法(使用df[['col1', 'col2']],右侧)的对比。出乎意料的是,Pandas 语法比建议的.select()方法快得多。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Polars 与 Pandas 语法(df[[‘col1’, ‘col2’]])选择时间的对比(图片由作者提供,通过Kaggle

虽然你会在 Pandas 中使用.query()方法来筛选数据,但在 Polars 中你需要使用.filter()方法。

# Pandas
df.query('col1 > 5')

# Polars
df.filter(pl.col('col') > 5)

下面显示了在 Pandas 和 Polars 中筛选数据的执行时间:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Pandas 和 Polars 之间筛选时间的对比(图片由作者提供,通过Kaggle

对于我们的样本数据集,筛选数据框所需的时间在 Pandas 和 Polars 中相似

与 Pandas 不同,Polars 可以并行运行.select().filter()中的操作。

创建新列

在 Polars 中创建新列也与 Pandas 有所不同。在 Polars 中,你需要根据要创建的列数使用.with_column().with_columns()方法。

# Pandas
df_pd["new_col"] = df_pd["col"] * 10

# Polars
df.with_columns([(pl.col("col") * 10).alias("new_col")])

# Polars for multiple columns
# df.with_columns([(pl.col("col") * 10).alias("new_col"), ...])

下面显示了在 Pandas 和 Polars 中创建新列的执行时间:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Pandas 和 Polars 创建新列的时间比较(图像由作者提供,通过 Kaggle

对于我们的示例数据集,使用 Polars 创建新列大约需要比 Pandas 多两倍的时间

分组和聚合

分组和聚合在 Pandas 和 Polars 之间的语法略有不同,但两者都使用 .groupby().agg() 方法。

# Pandas
df_pd.groupby('col1')['col2'].agg('mean')

# Polars
# df.groupby('col1').agg([pl.col('col2').mean()]) # As suggested in Polars docs
df.groupby('col1').agg([pl.mean('col2')]) # Shorter

以下是 Pandas 和 Polars 中分组和聚合数据的执行时间:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Pandas 和 Polars 聚合时间比较(图像由作者提供,通过 Kaggle

对于我们的示例数据集,使用 Pandas 聚合数据的时间约为 Polars 的两倍

缺失数据

Pandas 和 Polars 之间的另一个主要区别是 Pandas 使用 NaN 值来表示缺失值,而 Polars 使用 null [1]。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Pandas 和 Polars 在 DataFrames 中表示缺失值的方式(图像由作者提供)

因此,与 Pandas 的 .fillna() 方法相比,你应该使用 Polars 的 .fill_null() 方法。

# Pandas
df['col2'].fillna(-999)

# Polars
# df_pd.with_column(pl.col('col2').fill_null(pl.lit(-999))) # As suggested in Polars docs
df_pd.with_column(pl.col('col2').fill_null(-999)) # Shorter

结论

现在,Polars 是否比 Pandas 更好?Polars 会取代 Pandas 吗?

Polars 相对于 Pandas 的主要优势是其速度。如果你需要对大数据集进行大量数据处理,你应该尝试一下 Polars。

Polars 相对于 Pandas 的主要优势是其速度。

但正如本文所示,你需要学习新的 Polars 语法才能从 Pandas 切换到 Polars。此外,你已经看到,Polars 代码通常比 Pandas 在执行相同操作时稍长。最后但同样重要的是,Polars 并没有涵盖 Pandas 拥有的全部功能,例如数据探索。

Polars 代码通常比 Pandas 代码稍长。

有关进一步讨论,请参阅评论区,那里有更多经验丰富的 Polars 用户列出了他们的见解。

享受这篇故事吗?

如果你喜欢这篇文章,你可能也会喜欢我的其他 Pandas 文章。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Leonie Monigatti

Pandas

查看列表3 个故事!Pandas 与 Polars外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

免费订阅 以便在我发布新故事时收到通知。

[## 每当 Leonie Monigatti 发布新内容时,你将收到一封邮件。

每当 Leonie Monigatti 发布新内容时,你将收到一封邮件。通过注册,你将创建一个 Medium 账户,如果你还没有的话…

medium.com](https://medium.com/@iamleonie/subscribe?source=post_page-----5aa54e27497e--------------------------------)

在我的 LinkedInTwitter Kaggle 上找到我!

参考文献

[1] Polars (2023):用户指南 pola-rs.github.io/polars-book/user-guide/(访问日期:2023 年 1 月 8 日)

[2] “Stackoverflow”,“feather 和 parquet 之间有什么区别?” stackoverflow.com. stackoverflow.com/questions/48083405/what-are-the-differences-between-feather-and-parquet(访问日期:2022 年 7 月 25 日)

Pandas: 处理你的数据类型!

原文:towardsdatascience.com/pandas-work-on-your-dtypes-20d9d32d2e42

在 pandas 中拥有正确的数据类型是进行干净数据分析的必需条件。下面是原因和方法。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Yoann Mocquin

·发表于 Towards Data Science ·阅读时间 8 分钟·2023 年 9 月 26 日

为你的 Series 和 DataFrame 选择合适的数据类型非常重要,原因有很多:

  • 内存管理:为特定的系列选择正确的数据类型可以显著减少内存使用,进一步地,这也适用于数据框

  • 解释:其他任何人(无论是人还是计算机)都会根据数据类型对你的数据做出假设:如果一列全是整数却被存储为字符串,它们会将其视为字符串,而不是整数

  • 它强制要求你拥有干净的数据,例如处理缺失值或记录错误的值。这将大大简化后续的数据处理

可能还有很多其他原因,你能列举一些吗?如果可以,请在评论中写出来。

在我系列 pandas 的第一篇文章中,我想回顾 pandas 数据类型的基础知识。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由 Chris Curry 提供,来源于 Unsplash

我们首先会回顾 pandas 提供的可用数据类型,然后我将重点介绍 4 种有用的数据类型,它们能满足你 95% 的需求,即数值数据类型、布尔数据类型、字符串数据类型和分类数据类型

这篇文章的最终目标是让你对 pandas 中各种数据类型及其差异更加熟悉。

如果你对 pandas 和时间序列感兴趣,确保查看我关于时间序列傅里叶变换的文章:

  • 回顾卷积如何与傅里叶变换相关以及它的速度

## 时间序列的傅里叶变换:使用 numpy 解释快速卷积

使用傅里叶变换实现 10000 倍更快的卷积

[towardsdatascience.com

  • 通过图像示例深化你对卷积的理解:

[## 傅里叶变换用于时间序列:关于图像卷积和 SciPy]

傅里叶变换卷积同样适用于图像

towardsdatascience.com

  • 了解傅里叶变换如何通过向量可视化方法进行直观理解:

[## 傅里叶变换用于时间序列:绘制复数]

绘制傅里叶变换算法以理解它。

towardsdatascience.com

  • 查看去趋势技术如何显著改善傅里叶变换的输出:

[## 傅里叶变换用于时间序列:去趋势]

去趋势你的时间序列可能是一个改变游戏规则的因素。

towardsdatascience.com

回顾可用的数据类型

让我们花一分钟回顾一下 pandas 提供的数据类型。由于 pandas 基于 numpy,因此它们可以分为两类:

  • 基于 numpy 的数据类型

  • pandas 特定的数据类型

在底层,pandas 将你的数据存储在 numpy 数组中,因此使用 numpy 的数据类型。我们可以将这些视为终极低级数据类型。但为了方便起见,pandas 还暴露了由 pandas 团队特别创建的高级数据类型。

想法是,从你的角度来看,所有数据类型(无论是基于 numpy 还是 pandas 特定的)都被视为对你的 seriesdataframe 有效的数据类型。

基于 numpy 的数据类型如下:

  • **float**:用于存储浮点数(0.0245)

  • **int**:用于存储整数(1,-6)

  • **bool**:用于存储布尔值(True/False)

  • **datetime64[ns]**:用于存储时间线上的一个时刻(日期和时间)

  • **timedelta64[ns]**:用于存储相对持续时间(这补充了 datettime 数据类型)

  • **object**:可以存储任何 Python 对象

实际的 numpy 数据类型完整列表 比这更大,但我们将坚持上述内容。

然后 pandas 进入并暴露了许多新数据类型,包括:

  • **string**:另一种存储字符串的方式

  • **Nullable-int****Nullable-float**numpy**int****float** 更适合处理缺失值

  • **boolean**:比 numpy**bool** 更适合处理缺失值的布尔类型

  • **categorical**:适用于只能有特定值并能处理缺失条目的数据类型

再次,pandas 中定义了其他数据类型, 但我想专注于这四种,因为我发现它们最有用。

数据类型的设置方式

实际上,你的数据类型可以有两种来源:

  • 要么你没有指定数据类型,而 pandas 在创建系列/数据框时做了假设(无论是从加载 csv 还是创建类似 s = pd.Series([1, 2, 3]) 的对象)。这种情况通常会有 50% 到 80% 的成功率,具体取决于输入数据的格式。

  • 要么你指定数据类型,通过明确告知 pandas 每个列/系列使用什么数据类型

对于第一种情况:

  • 优点:更简单更快速

  • 缺点:除非你在之后审查每个数据类型,否则你不知道发生了什么,可能没有最合适的数据类型(例如 object 因为 pandas 没有确定列的内容),甚至可能为某些列选择了非常不合适的数据类型

对于第二种情况:

  • 优点:你准确知道数据发生了什么,确切知道列的数据类型,知道你是如何处理缺失和不良条件值的。换句话说,你的数据已经准备好进行实际处理

  • 缺点:需要更多时间和更多代码

最后,我建议以下做法:首先,让 pandas 推断数据类型并尽力而为。然后审查每一列,并手动设置你认为应该更改的数据类型。

我们将在下一篇文章中讨论如何做所有这些,但现在我想回顾一下可用的数据类型及其存在的原因。

由于大多数情况下我最终只使用所有可用数据类型的一个子集,所以我会专注于这些:

  • 数值数据类型,主要是 float 和 int

  • 布尔数据类型

  • 类似字符串的(包括字符串和对象)数据类型

  • 类别数据类型

类似数值的数据类型

关于数值数据类型,numpy 提供了一个坚实的基础:整数和浮点数数据类型,也能处理 *np.nan*。还要注意,默认使用的数值数据类型是 int64float64。这可能不适合你的数据,考虑到内存使用和给定系列的显式允许值:

pd.Series([1, 2, 3])                     # dtype: int64
pd.Series([1, 2, 3], dtype="int")        # dtype: int64
pd.Series([1, 2, 3], dtype='float')      # dtype: float64

pd.Series([1, 2, np.nan])                # dtype: float64
pd.Series([1, 2, np.nan], dtype="int")   # dtype: float64
pd.Series([1, 2, np.nan], dtype='float') # dtype: float64

pd.Series([1, 2, pd.NA])                 # dtype: object
# fails since pd.NA cannot be converted to an int
# pd.Series([1, 2, pd.NA], dtype="int"))
# fails since pd.NA cannot be converted to an int
# pd.Series([1, 2, pd.NA], dtype='float'))

注意,一旦使用 ***np.nan***,数据类型会被转换为 float。因此,pandas 还提供了能够处理缺失值并保持显式底层数值数据类型的数据类型,如 ***Int64Dtype***具体理由见这里)。

pd.Series([1, 2, 3, np.nan], dtype="Int64")   # dtype: Int64
pd.Series([1, 2, 3, pd.NA], dtype="Int64")    # dtype: Int64
pd.Series([1, 2, 3, np.nan], dtype="Float32") # dtype: Float32
pd.Series([1, 2, 3, pd.NA], dtype="Float32")  # dtype: Float32

这样,我们可以兼得两全:一个明确的底层数值数据类型(int64,float32 等),并使用 ***pd.NA*** 处理缺失值。

布尔类数据类型

基本上,有 2 种数据类型类似于布尔值,即‘bool’ 和 ‘boolean’。

bool’ 对应于标准的 numpy 布尔类型,因此不能包含‘NA’,因为布尔 numpy 数组只能存储 TrueFalse

为了处理“不可用”条目——或“NA”——pandas 提供了数据类型‘boolean’,它可以包含‘NA’。见下面的示例:

pd.Series([True, False], dtype='bool')              # numpy-boolean
pd.Series([True, False, pd.NA], dtype='boolean')    # pandas-boolean
pd.Series([True, False, np.nan], dtype='boolean')   # pandas-boolean

# this cannot work, since numpy does not handle pd.NA
# pd.Series([True, False, pd.NA], dtype='bool') 

# this works, but np.nan is converted to True...
# pd.Series([True, False, np.nan], dtype="bool") # --> dtype: object, not boolean...

# if no dtype is passed, pandas tries to infer an appropriate one
pd.Series([True, False])         # --> dtype: bool
pd.Series([True, False, pd.NA])  # --> dtype: object, not boolean...
pd.Series([True, False, np.nan]) # --> dtype: object, not boolean...

字符串类数据类型

本质上,字符串可以存储在 numpy 数组中,因为我们可以使用 object 数据类型,该数据类型用于处理“任何 Python 对象”。

字符串与大多数其他数据类型不同,因为不能提前知道字符串的长度,因此也就无法预估所需的内存。这同样适用于任何自定义的 Python 对象,不论其简单还是复杂,都需要不同数量的内存。

因此,我们可以在 pandas 中使用‘object’ 数据类型,因为它在 numpy 中是可用的:

pd.Series(['toto', 'titi', 'tata'])                 # --> dtype: object
pd.Series(['toto', 'titi', 'tata'], dtype="object") # --> dtype: object
pd.Series(['toto', 'titi', 'tata'], dtype="str")    # --> dtype: object
pd.Series(['toto', 'titi', np.nan], dtype="str")    # --> dtype: object
pd.Series(['toto', 'titi', pd.NA], dtype="str")     # --> dtype: object

此外,pandas 创建了一种数据类型,使得数据是字符串这一点变得明确:***StringDtype***,可以指定为 ***string***,这更好,因为“显式优于隐式”,并且与 pandas 的其他生态系统接口更好(理由在这里):

pd.Series(['toto', 'titi', 'tata'], dtype="string") # --> dtype: string
pd.Series(['toto', 'titi', np.nan], dtype="string") # --> dtype: string
pd.Series(['toto', 'titi', pd.NA], dtype="string")  # --> dtype: string

请注意,大多数情况下,你需要挑战自己,问自己:我真的需要将这个系列存储为字符串吗?这些字符串是否只是其他数据的表示,比如数值数据或分类数据?如果是这样,你可能需要转换这些系列的数据类型。关注我的下一篇文章,了解如何做到这一点!

万能数据类型:分类数据类型

我建议你试试这个方法:在 pandas 中打开你的一个数据集,一一检查列,并问自己:这个特征是否可以存储为分类数据类型

我敢打赌,你会比预期的更容易接受这个问题的答案。

这种数据类型特别适用于通常存储为类似整数的数字(0,1,2 等)和/或字符串(‘Male’/’Female’,‘Dog’/’Cat’/’Other’)的内容。

这些数据类型在某些情况下可以显著提高速度和内存使用效率。它还再次明确告知他人(包括人类和计算机)这一特定数据表示一个类别,并应被如此处理。

pd.Series([1, 2, 3, 2], dtype="category")           # dtype: category, with 3 int64 possible values [1, 2, 3]
pd.Series([1, 2, 'a', 1], dtype="category")         # dtype: category, with 4 object-like possible values [1, 2, 'a']
pd.Series(["a", "b", "c", "a"], dtype="category")   # dtype: category, with 3 object-like possible values ['a', 'b', 'c']
pd.Series(["M", "F", "M", "F"], dtype="category")   # dtype: category, with 2 object-like possible values ['M', 'F']

总结

其他数据类型在 pandas 中也有实现,但我发现它们的使用频率不如上述数据类型。

所以请记住:

  • 好的数据类型对于你的处理至关重要,尽早审查并设置合适的数据类型会使你未来的工作变得更加轻松。同时,它也可能节省大量内存和处理复杂性

  • 在使用 objectstring 数据类型之前,考虑使用 categorical 数据类型

  • 如果处理缺失值或 NaN,请考虑使用 pandas 数据类型如 boolean,而不是 numpy 的 bool

  • 仅在数据复杂和/或不适合任何其他数据类型时使用 object 数据类型

在下一篇文章中,我们将查看如何检查现有 Series/DataFrame 的数据类型,以及如何将它们转换为其他数据类型。

如果你正在考虑加入 Medium 并获得无限访问我和其他人的文章,请使用此链接快速订阅并成为我推荐的会员:

[## 使用我的推荐链接加入 Medium - Yoann Mocquin

作为 Medium 会员,你的会员费用的一部分将用于你阅读的作者,而你将获得对每篇故事的完全访问…

medium.com

然后订阅以获取未来的文章通知:

[## 订阅以获取我的新文章!

订阅以获取我发布的电子邮件!新发布将包括数据转换、先进的绘图和模拟…

mocquin.medium.com

最后,查看我其他的一些文章:

## 使用 numpy 提高 300 倍的有限差分法分辨率

有限差分法是一种强大的技术来解决复杂问题,而 numpy 使其变得快速!

[towardsdatascience.com ## PCA/LDA/ICA:组件分析算法比较

回顾这些著名算法的概念和差异。

[towardsdatascience.com [## 一样本 t 检验,直观解释

介绍其中一种最著名的统计检验

mocquin.medium.com ## 包装 numpy 数组

容器方法。

[towardsdatascience.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值