Pandas 2.2 中文官方教程和指南(四)(2)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云解析 DNS,旗舰版 1个月
简介: Pandas 2.2 中文官方教程和指南(四)

Pandas 2.2 中文官方教程和指南(四)(1)https://developer.aliyun.com/article/1509879

RIGHT JOIN

显示df2中的所有记录。

SELECT  *
FROM  df1
RIGHT  OUTER  JOIN  df2
  ON  df1.key  =  df2.key; 
In [30]: pd.merge(df1, df2, on="key", how="right")
Out[30]: 
 key   value_x   value_y
0   B -0.282863  1.212112
1   D -1.135632 -0.173215
2   D -1.135632  0.119209
3   E       NaN -1.044236 

FULL JOIN

pandas 还允许进行FULL JOIN,它会显示数据集的两侧,无论连接列是否找到匹配。截至目前,不是所有的 RDBMS(MySQL)都支持FULL JOIN

显示两个表中的所有记录。

SELECT  *
FROM  df1
FULL  OUTER  JOIN  df2
  ON  df1.key  =  df2.key; 
In [31]: pd.merge(df1, df2, on="key", how="outer")
Out[31]: 
 key   value_x   value_y
0   A  0.469112       NaN
1   B -0.282863  1.212112
2   C -1.509059       NaN
3   D -1.135632 -0.173215
4   D -1.135632  0.119209
5   E       NaN -1.044236 

INNER JOIN

SELECT  *
FROM  df1
INNER  JOIN  df2
  ON  df1.key  =  df2.key; 
# merge performs an INNER JOIN by default
In [26]: pd.merge(df1, df2, on="key")
Out[26]: 
 key   value_x   value_y
0   B -0.282863  1.212112
1   D -1.135632 -0.173215
2   D -1.135632  0.119209 

merge()还提供参数,用于在您希望将一个数据框的列与另一个数据框的索引进行连接的情况。

In [27]: indexed_df2 = df2.set_index("key")
In [28]: pd.merge(df1, indexed_df2, left_on="key", right_index=True)
Out[28]: 
 key   value_x   value_y
1   B -0.282863  1.212112
3   D -1.135632 -0.173215
3   D -1.135632  0.119209 

LEFT OUTER JOIN

显示df1中的所有记录。

SELECT  *
FROM  df1
LEFT  OUTER  JOIN  df2
  ON  df1.key  =  df2.key; 
In [29]: pd.merge(df1, df2, on="key", how="left")
Out[29]: 
 key   value_x   value_y
0   A  0.469112       NaN
1   B -0.282863  1.212112
2   C -1.509059       NaN
3   D -1.135632 -0.173215
4   D -1.135632  0.119209 

RIGHT JOIN

显示df2中的所有记录。

SELECT  *
FROM  df1
RIGHT  OUTER  JOIN  df2
  ON  df1.key  =  df2.key; 
In [30]: pd.merge(df1, df2, on="key", how="right")
Out[30]: 
 key   value_x   value_y
0   B -0.282863  1.212112
1   D -1.135632 -0.173215
2   D -1.135632  0.119209
3   E       NaN -1.044236 

FULL JOIN

pandas 还允许进行FULL JOIN,它会显示数据集的两侧,无论连接列是否找到匹配。截至目前,不是所有的 RDBMS(MySQL)都支持FULL JOIN

显示两个表中的所有记录。

SELECT  *
FROM  df1
FULL  OUTER  JOIN  df2
  ON  df1.key  =  df2.key; 
In [31]: pd.merge(df1, df2, on="key", how="outer")
Out[31]: 
 key   value_x   value_y
0   A  0.469112       NaN
1   B -0.282863  1.212112
2   C -1.509059       NaN
3   D -1.135632 -0.173215
4   D -1.135632  0.119209
5   E       NaN -1.044236 

UNION

可以使用concat()执行UNION ALL

In [32]: df1 = pd.DataFrame(
 ....:    {"city": ["Chicago", "San Francisco", "New York City"], "rank": range(1, 4)}
 ....: )
 ....: 
In [33]: df2 = pd.DataFrame(
 ....:    {"city": ["Chicago", "Boston", "Los Angeles"], "rank": [1, 4, 5]}
 ....: )
 ....: 
SELECT  city,  rank
FROM  df1
UNION  ALL
SELECT  city,  rank
FROM  df2;
/*
 city  rank
 Chicago     1
San Francisco     2
New York City     3
 Chicago     1
 Boston     4
 Los Angeles     5
*/ 
In [34]: pd.concat([df1, df2])
Out[34]: 
 city  rank
0        Chicago     1
1  San Francisco     2
2  New York City     3
0        Chicago     1
1         Boston     4
2    Los Angeles     5 

SQL 的UNION类似于UNION ALL,但UNION会删除重复行。

SELECT  city,  rank
FROM  df1
UNION
SELECT  city,  rank
FROM  df2;
-- notice that there is only one Chicago record this time
/*
 city  rank
 Chicago     1
San Francisco     2
New York City     3
 Boston     4
 Los Angeles     5
*/ 

在 pandas 中,您可以结合使用 concat()drop_duplicates()

In [35]: pd.concat([df1, df2]).drop_duplicates()
Out[35]: 
 city  rank
0        Chicago     1
1  San Francisco     2
2  New York City     3
1         Boston     4
2    Los Angeles     5 

限制

SELECT  *  FROM  tips
LIMIT  10; 
In [36]: tips.head(10)
Out[36]: 
 total_bill   tip     sex smoker  day    time  size
0       16.99  1.01  Female     No  Sun  Dinner     2
1       10.34  1.66    Male     No  Sun  Dinner     3
2       21.01  3.50    Male     No  Sun  Dinner     3
3       23.68  3.31    Male     No  Sun  Dinner     2
4       24.59  3.61  Female     No  Sun  Dinner     4
5       25.29  4.71    Male     No  Sun  Dinner     4
6        8.77  2.00    Male     No  Sun  Dinner     2
7       26.88  3.12    Male     No  Sun  Dinner     4
8       15.04  1.96    Male     No  Sun  Dinner     2
9       14.78  3.23    Male     No  Sun  Dinner     2 

pandas 中一些 SQL 分析和聚合函数的等效函数

带有偏移的前 n 行

-- MySQL
SELECT  *  FROM  tips
ORDER  BY  tip  DESC
LIMIT  10  OFFSET  5; 
In [37]: tips.nlargest(10 + 5, columns="tip").tail(10)
Out[37]: 
 total_bill   tip     sex smoker   day    time  size
183       23.17  6.50    Male    Yes   Sun  Dinner     4
214       28.17  6.50  Female    Yes   Sat  Dinner     3
47        32.40  6.00    Male     No   Sun  Dinner     4
239       29.03  5.92    Male     No   Sat  Dinner     3
88        24.71  5.85    Male     No  Thur   Lunch     2
181       23.33  5.65    Male    Yes   Sun  Dinner     2
44        30.40  5.60    Male     No   Sun  Dinner     4
52        34.81  5.20  Female     No   Sun  Dinner     4
85        34.83  5.17  Female     No  Thur   Lunch     4
211       25.89  5.16    Male    Yes   Sat  Dinner     4 

每个组的前 n 行

-- Oracle's ROW_NUMBER() analytic function
SELECT  *  FROM  (
  SELECT
  t.*,
  ROW_NUMBER()  OVER(PARTITION  BY  day  ORDER  BY  total_bill  DESC)  AS  rn
  FROM  tips  t
)
WHERE  rn  <  3
ORDER  BY  day,  rn; 
In [38]: (
 ....:    tips.assign(
 ....:        rn=tips.sort_values(["total_bill"], ascending=False)
 ....:        .groupby(["day"])
 ....:        .cumcount()
 ....:        + 1
 ....:    )
 ....:    .query("rn < 3")
 ....:    .sort_values(["day", "rn"])
 ....: )
 ....: 
Out[38]: 
 total_bill    tip     sex smoker   day    time  size  rn
95        40.17   4.73    Male    Yes   Fri  Dinner     4   1
90        28.97   3.00    Male    Yes   Fri  Dinner     2   2
170       50.81  10.00    Male    Yes   Sat  Dinner     3   1
212       48.33   9.00    Male     No   Sat  Dinner     4   2
156       48.17   5.00    Male     No   Sun  Dinner     6   1
182       45.35   3.50    Male    Yes   Sun  Dinner     3   2
197       43.11   5.00  Female    Yes  Thur   Lunch     4   1
142       41.19   5.00    Male     No  Thur   Lunch     5   2 

使用 rank(method='first') 函数相同

In [39]: (
 ....:    tips.assign(
 ....:        rnk=tips.groupby(["day"])["total_bill"].rank(
 ....:            method="first", ascending=False
 ....:        )
 ....:    )
 ....:    .query("rnk < 3")
 ....:    .sort_values(["day", "rnk"])
 ....: )
 ....: 
Out[39]: 
 total_bill    tip     sex smoker   day    time  size  rnk
95        40.17   4.73    Male    Yes   Fri  Dinner     4  1.0
90        28.97   3.00    Male    Yes   Fri  Dinner     2  2.0
170       50.81  10.00    Male    Yes   Sat  Dinner     3  1.0
212       48.33   9.00    Male     No   Sat  Dinner     4  2.0
156       48.17   5.00    Male     No   Sun  Dinner     6  1.0
182       45.35   3.50    Male    Yes   Sun  Dinner     3  2.0
197       43.11   5.00  Female    Yes  Thur   Lunch     4  1.0
142       41.19   5.00    Male     No  Thur   Lunch     5  2.0 
-- Oracle's RANK() analytic function
SELECT  *  FROM  (
  SELECT
  t.*,
  RANK()  OVER(PARTITION  BY  sex  ORDER  BY  tip)  AS  rnk
  FROM  tips  t
  WHERE  tip  <  2
)
WHERE  rnk  <  3
ORDER  BY  sex,  rnk; 

让我们找到每个性别组中 (rank < 3) 的小费,对于 (tips < 2)。请注意,当使用 rank(method='min') 函数时,相同 tiprnk_min 保持不变(类似于 Oracle 的 RANK() 函数)

In [40]: (
 ....:    tips[tips["tip"] < 2]
 ....:    .assign(rnk_min=tips.groupby(["sex"])["tip"].rank(method="min"))
 ....:    .query("rnk_min < 3")
 ....:    .sort_values(["sex", "rnk_min"])
 ....: )
 ....: 
Out[40]: 
 total_bill   tip     sex smoker  day    time  size  rnk_min
67         3.07  1.00  Female    Yes  Sat  Dinner     1      1.0
92         5.75  1.00  Female    Yes  Fri  Dinner     2      1.0
111        7.25  1.00  Female     No  Sat  Dinner     1      1.0
236       12.60  1.00    Male    Yes  Sat  Dinner     2      1.0
237       32.83  1.17    Male    Yes  Sat  Dinner     2      2.0 

带有偏移的前 n 行

-- MySQL
SELECT  *  FROM  tips
ORDER  BY  tip  DESC
LIMIT  10  OFFSET  5; 
In [37]: tips.nlargest(10 + 5, columns="tip").tail(10)
Out[37]: 
 total_bill   tip     sex smoker   day    time  size
183       23.17  6.50    Male    Yes   Sun  Dinner     4
214       28.17  6.50  Female    Yes   Sat  Dinner     3
47        32.40  6.00    Male     No   Sun  Dinner     4
239       29.03  5.92    Male     No   Sat  Dinner     3
88        24.71  5.85    Male     No  Thur   Lunch     2
181       23.33  5.65    Male    Yes   Sun  Dinner     2
44        30.40  5.60    Male     No   Sun  Dinner     4
52        34.81  5.20  Female     No   Sun  Dinner     4
85        34.83  5.17  Female     No  Thur   Lunch     4
211       25.89  5.16    Male    Yes   Sat  Dinner     4 

每个组的前 n 行

-- Oracle's ROW_NUMBER() analytic function
SELECT  *  FROM  (
  SELECT
  t.*,
  ROW_NUMBER()  OVER(PARTITION  BY  day  ORDER  BY  total_bill  DESC)  AS  rn
  FROM  tips  t
)
WHERE  rn  <  3
ORDER  BY  day,  rn; 
In [38]: (
 ....:    tips.assign(
 ....:        rn=tips.sort_values(["total_bill"], ascending=False)
 ....:        .groupby(["day"])
 ....:        .cumcount()
 ....:        + 1
 ....:    )
 ....:    .query("rn < 3")
 ....:    .sort_values(["day", "rn"])
 ....: )
 ....: 
Out[38]: 
 total_bill    tip     sex smoker   day    time  size  rn
95        40.17   4.73    Male    Yes   Fri  Dinner     4   1
90        28.97   3.00    Male    Yes   Fri  Dinner     2   2
170       50.81  10.00    Male    Yes   Sat  Dinner     3   1
212       48.33   9.00    Male     No   Sat  Dinner     4   2
156       48.17   5.00    Male     No   Sun  Dinner     6   1
182       45.35   3.50    Male    Yes   Sun  Dinner     3   2
197       43.11   5.00  Female    Yes  Thur   Lunch     4   1
142       41.19   5.00    Male     No  Thur   Lunch     5   2 

使用 rank(method='first') 函数相同

In [39]: (
 ....:    tips.assign(
 ....:        rnk=tips.groupby(["day"])["total_bill"].rank(
 ....:            method="first", ascending=False
 ....:        )
 ....:    )
 ....:    .query("rnk < 3")
 ....:    .sort_values(["day", "rnk"])
 ....: )
 ....: 
Out[39]: 
 total_bill    tip     sex smoker   day    time  size  rnk
95        40.17   4.73    Male    Yes   Fri  Dinner     4  1.0
90        28.97   3.00    Male    Yes   Fri  Dinner     2  2.0
170       50.81  10.00    Male    Yes   Sat  Dinner     3  1.0
212       48.33   9.00    Male     No   Sat  Dinner     4  2.0
156       48.17   5.00    Male     No   Sun  Dinner     6  1.0
182       45.35   3.50    Male    Yes   Sun  Dinner     3  2.0
197       43.11   5.00  Female    Yes  Thur   Lunch     4  1.0
142       41.19   5.00    Male     No  Thur   Lunch     5  2.0 
-- Oracle's RANK() analytic function
SELECT  *  FROM  (
  SELECT
  t.*,
  RANK()  OVER(PARTITION  BY  sex  ORDER  BY  tip)  AS  rnk
  FROM  tips  t
  WHERE  tip  <  2
)
WHERE  rnk  <  3
ORDER  BY  sex,  rnk; 

让我们找到每个性别组中 (rank < 3) 的小费,对于 (tips < 2)。请注意,当使用 rank(method='min') 函数时,相同 tiprnk_min 保持不变(类似于 Oracle 的 RANK() 函数)

In [40]: (
 ....:    tips[tips["tip"] < 2]
 ....:    .assign(rnk_min=tips.groupby(["sex"])["tip"].rank(method="min"))
 ....:    .query("rnk_min < 3")
 ....:    .sort_values(["sex", "rnk_min"])
 ....: )
 ....: 
Out[40]: 
 total_bill   tip     sex smoker  day    time  size  rnk_min
67         3.07  1.00  Female    Yes  Sat  Dinner     1      1.0
92         5.75  1.00  Female    Yes  Fri  Dinner     2      1.0
111        7.25  1.00  Female     No  Sat  Dinner     1      1.0
236       12.60  1.00    Male    Yes  Sat  Dinner     2      1.0
237       32.83  1.17    Male    Yes  Sat  Dinner     2      2.0 

更新

UPDATE  tips
SET  tip  =  tip*2
WHERE  tip  <  2; 
In [41]: tips.loc[tips["tip"] < 2, "tip"] *= 2 

删除

DELETE  FROM  tips
WHERE  tip  >  9; 

在 pandas 中,我们选择应该保留的行,而不是删除它们:

In [42]: tips = tips.loc[tips["tip"] <= 9] 

与电子表格的比较

原文:pandas.pydata.org/docs/getting_started/comparison/comparison_with_spreadsheets.html

由于许多潜在的 pandas 用户对电子表格程序(如 Excel)有一定的了解,因此本页面旨在提供使用 pandas 执行各种电子表格操作的示例。本页面将使用 Excel 的术语和链接到文档,但在 Google SheetsLibreOffice CalcApple Numbers 和其他兼容 Excel 的电子表格软件中,情况将是相同/类似的。

如果您是 pandas 的新手,您可能首先想阅读 10 分钟入门 pandas 来熟悉该库。

惯例上,我们导入 pandas 和 NumPy 如下:

In [1]: import pandas as pd
In [2]: import numpy as np 

数据结构

通用术语翻译

pandas Excel
DataFrame 工作表
Series
Index 行标题
NaN 空单元格

DataFrame

在 pandas 中,DataFrame类似于 Excel 工作表。虽然 Excel 工作簿可以包含多个工作表,但 pandas 的DataFrame是独立存在的。

Series

Series 是表示DataFrame的一列的数据结构。与处理电子表格的列类似,操作Series

Index

每个DataFrameSeries都有一个Index,这些是数据的上的标签。在 pandas 中,如果没有指定索引,默认使用 RangeIndex(第一行 = 0,第二行 = 1,依此类推),类似于电子表格中的行标题/编号。

在 pandas 中,索引可以设置为一个(或多个)唯一值,就像在工作表中使用作为行标识符的列一样。与大多数电子表格不同,这些Index值实际上可以用于引用行。(请注意,在 Excel 中可以使用结构引用执行此操作。)例如,在电子表格中,您可以将第一行引用为A1:Z1,而在 pandas 中,您可以使用populations.loc['Chicago']

索引值也是持久的,因此���果重新排列DataFrame中的行,特定行的标签不会改变。

查看 索引文档 以了解如何有效使用Index

复制 vs. 原地操作

大多数 pandas 操作返回Series/DataFrame的副本。要使更改“生效”,您需要将其分配给一个新变量:

sorted_df = df.sort_values("col1") 

或覆盖原始数据:

df = df.sort_values("col1") 

注意

您将看到一些方法可用的 inplace=Truecopy=False 关键字参数:

df.replace(5, inplace=True) 

目前正在就大多数方法(例如 dropna)废弃和移除 inplacecopy 进行积极讨论,除了一小部分方法(包括 replace)之外。在写时复制的情况下,这两个关键字将不再必要。提案可以在这里找到。

数据输入/输出

从值构建 DataFrame

在电子表格中,值可以直接输入到单元格中

一个 pandas DataFrame 可以以许多不同的方式构建,但对于少量值,通常将其指定为 Python 字典是方便的,其中键是列名,值是数据。

In [3]: df = pd.DataFrame({"x": [1, 3, 5], "y": [2, 4, 6]})
In [4]: df
Out[4]: 
 x  y
0  1  2
1  3  4
2  5  6 

读取外部数据

Excel 和 pandas 都可以从各种来源以各种格式导入数据。

CSV

让我们加载并显示来自 pandas 测试的tips数据集,这是一个 CSV 文件。在 Excel 中,您会下载然后打开 CSV。在 pandas 中,您将 URL 或本地路径传递给 read_csv()

In [5]: url = (
 ...:    "https://raw.githubusercontent.com/pandas-dev"
 ...:    "/pandas/main/pandas/tests/io/data/csv/tips.csv"
 ...: )
 ...: 
In [6]: tips = pd.read_csv(url)
In [7]: tips
Out[7]: 
 total_bill   tip     sex smoker   day    time  size
0         16.99  1.01  Female     No   Sun  Dinner     2
1         10.34  1.66    Male     No   Sun  Dinner     3
2         21.01  3.50    Male     No   Sun  Dinner     3
3         23.68  3.31    Male     No   Sun  Dinner     2
4         24.59  3.61  Female     No   Sun  Dinner     4
..          ...   ...     ...    ...   ...     ...   ...
239       29.03  5.92    Male     No   Sat  Dinner     3
240       27.18  2.00  Female    Yes   Sat  Dinner     2
241       22.67  2.00    Male    Yes   Sat  Dinner     2
242       17.82  1.75    Male     No   Sat  Dinner     2
243       18.78  3.00  Female     No  Thur  Dinner     2
[244 rows x 7 columns] 

Excel 的文本导入向导一样,read_csv 可以接受多个参数来指定数据应如何解析。例如,如果数据实际上是制表符分隔的,并且没有列名,那么 pandas 命令将是:

tips = pd.read_csv("tips.csv", sep="\t", header=None)
# alternatively, read_table is an alias to read_csv with tab delimiter
tips = pd.read_table("tips.csv", header=None) 
Excel 文件

Excel 通过双击打开各种 Excel 文件格式,或使用打开菜单。在 pandas 中,您可以使用特殊方法来读取和写入 Excel 文件。

让我们首先根据上面示例中的 tips 数据框创建一个新的 Excel 文件:

tips.to_excel("./tips.xlsx") 

如果您希望随后访问 tips.xlsx 文件中的数据,可以使用以下方式将其读入您的模块中

tips_df = pd.read_excel("./tips.xlsx", index_col=0) 

你刚刚使用 pandas 读取了一个 Excel 文件!

限制输出

电子表格程序一次只会显示一个屏幕的数据,然后允许你滚动,因此实际上不需要限制输出。在 pandas 中,你需要更多地考虑如何控制你的DataFrame的显示方式。

默认情况下,pandas 会截断大型DataFrame的输出以显示第一行和最后一行。这可以通过更改 pandas 选项,或使用DataFrame.head()DataFrame.tail()来覆盖。

In [8]: tips.head(5)
Out[8]: 
 total_bill   tip     sex smoker  day    time  size
0       16.99  1.01  Female     No  Sun  Dinner     2
1       10.34  1.66    Male     No  Sun  Dinner     3
2       21.01  3.50    Male     No  Sun  Dinner     3
3       23.68  3.31    Male     No  Sun  Dinner     2
4       24.59  3.61  Female     No  Sun  Dinner     4 

导出数据

默认情况下,桌面电子表格软件会保存到其相应的文件格式(.xlsx.ods等)。但是,你可以保存到其他文件格式

pandas 可以创建 Excel 文件,CSV,或其他多种格式。

数据操作

列上的操作

在电子表格中,公式通常在单独的单元格中创建,然后通过拖动到其他单元格中以计算其他列的值。在 pandas 中,你可以直接对整列进行操作。

pandas 通过在DataFrame中指定单独的Series提供矢量化操作。新列可以以相同的方式分配。DataFrame.drop()方法从DataFrame中删除列。

In [9]: tips["total_bill"] = tips["total_bill"] - 2
In [10]: tips["new_bill"] = tips["total_bill"] / 2
In [11]: tips
Out[11]: 
 total_bill   tip     sex smoker   day    time  size  new_bill
0         14.99  1.01  Female     No   Sun  Dinner     2     7.495
1          8.34  1.66    Male     No   Sun  Dinner     3     4.170
2         19.01  3.50    Male     No   Sun  Dinner     3     9.505
3         21.68  3.31    Male     No   Sun  Dinner     2    10.840
4         22.59  3.61  Female     No   Sun  Dinner     4    11.295
..          ...   ...     ...    ...   ...     ...   ...       ...
239       27.03  5.92    Male     No   Sat  Dinner     3    13.515
240       25.18  2.00  Female    Yes   Sat  Dinner     2    12.590
241       20.67  2.00    Male    Yes   Sat  Dinner     2    10.335
242       15.82  1.75    Male     No   Sat  Dinner     2     7.910
243       16.78  3.00  Female     No  Thur  Dinner     2     8.390
[244 rows x 8 columns]
In [12]: tips = tips.drop("new_bill", axis=1) 

请注意,我们不需要逐个单元格地告诉它执行减法 — pandas 会为我们处理。查看如何从现有列创建新列。

过滤

在 Excel 中,过滤是通过图形菜单完成的。

数据框可以通过多种方式进行过滤;其中最直观的是使用布尔索引。

In [13]: tips[tips["total_bill"] > 10]
Out[13]: 
 total_bill   tip     sex smoker   day    time  size
0         14.99  1.01  Female     No   Sun  Dinner     2
2         19.01  3.50    Male     No   Sun  Dinner     3
3         21.68  3.31    Male     No   Sun  Dinner     2
4         22.59  3.61  Female     No   Sun  Dinner     4
5         23.29  4.71    Male     No   Sun  Dinner     4
..          ...   ...     ...    ...   ...     ...   ...
239       27.03  5.92    Male     No   Sat  Dinner     3
240       25.18  2.00  Female    Yes   Sat  Dinner     2
241       20.67  2.00    Male    Yes   Sat  Dinner     2
242       15.82  1.75    Male     No   Sat  Dinner     2
243       16.78  3.00  Female     No  Thur  Dinner     2
[204 rows x 7 columns] 

上述语句只是将True/False对象的Series传递给数据框,返回所有具有True的��。

In [14]: is_dinner = tips["time"] == "Dinner"
In [15]: is_dinner
Out[15]: 
0      True
1      True
2      True
3      True
4      True
 ... 
239    True
240    True
241    True
242    True
243    True
Name: time, Length: 244, dtype: bool
In [16]: is_dinner.value_counts()
Out[16]: 
time
True     176
False     68
Name: count, dtype: int64
In [17]: tips[is_dinner]
Out[17]: 
 total_bill   tip     sex smoker   day    time  size
0         14.99  1.01  Female     No   Sun  Dinner     2
1          8.34  1.66    Male     No   Sun  Dinner     3
2         19.01  3.50    Male     No   Sun  Dinner     3
3         21.68  3.31    Male     No   Sun  Dinner     2
4         22.59  3.61  Female     No   Sun  Dinner     4
..          ...   ...     ...    ...   ...     ...   ...
239       27.03  5.92    Male     No   Sat  Dinner     3
240       25.18  2.00  Female    Yes   Sat  Dinner     2
241       20.67  2.00    Male    Yes   Sat  Dinner     2
242       15.82  1.75    Male     No   Sat  Dinner     2
243       16.78  3.00  Female     No  Thur  Dinner     2
[176 rows x 7 columns] 

If/then 逻辑

假设我们想要根据total_bill是小于还是大于$10 来创建一个bucket列,值为lowhigh

在电子表格中,可以使用条件公式进行逻辑比较。我们会使用公式=IF(A2 < 10, "low", "high"),拖动到新的bucket列中的所有单元格。

在 pandas 中,可以使用numpy中的where方法来完成相同的操作。

In [18]: tips["bucket"] = np.where(tips["total_bill"] < 10, "low", "high")
In [19]: tips
Out[19]: 
 total_bill   tip     sex smoker   day    time  size bucket
0         14.99  1.01  Female     No   Sun  Dinner     2   high
1          8.34  1.66    Male     No   Sun  Dinner     3    low
2         19.01  3.50    Male     No   Sun  Dinner     3   high
3         21.68  3.31    Male     No   Sun  Dinner     2   high
4         22.59  3.61  Female     No   Sun  Dinner     4   high
..          ...   ...     ...    ...   ...     ...   ...    ...
239       27.03  5.92    Male     No   Sat  Dinner     3   high
240       25.18  2.00  Female    Yes   Sat  Dinner     2   high
241       20.67  2.00    Male    Yes   Sat  Dinner     2   high
242       15.82  1.75    Male     No   Sat  Dinner     2   high
243       16.78  3.00  Female     No  Thur  Dinner     2   high
[244 rows x 8 columns] 

日期功能

本节将涉及“日期”,但时间戳处理方式类似。

我们可以将日期功能分为两部分:解析和输出。在电子表格中,日期值通常会自动解析,尽管如果需要,可以使用DATEVALUE函数。在 pandas 中,您需要显式将纯文本转换为日期时间对象,可以在从 CSV 读取时或在 DataFrame 中的某个时刻进行转换。

解析后,电子表格会以默认格式显示日期,尽管格式可以更改。在 pandas 中,您通常希望在进行计算时将日期保留为datetime对象。在电子表格中,输出日期的部分(如年份)是通过日期函数完成的,在 pandas 中则通过 datetime 属性完成。

在电子表格中,如果在列AB中给出date1date2,你可能会有这些公式:

公式
date1_year =YEAR(A2)
date2_month =MONTH(B2)
date1_next =DATE(YEAR(A2),MONTH(A2)+1,1)
months_between =DATEDIF(A2,B2,"M")

下面显示了等效的 pandas 操作。

In [20]: tips["date1"] = pd.Timestamp("2013-01-15")
In [21]: tips["date2"] = pd.Timestamp("2015-02-15")
In [22]: tips["date1_year"] = tips["date1"].dt.year
In [23]: tips["date2_month"] = tips["date2"].dt.month
In [24]: tips["date1_next"] = tips["date1"] + pd.offsets.MonthBegin()
In [25]: tips["months_between"] = tips["date2"].dt.to_period("M") - tips[
 ....:    "date1"
 ....: ].dt.to_period("M")
 ....: 
In [26]: tips[
 ....:    ["date1", "date2", "date1_year", "date2_month", "date1_next", "months_between"]
 ....: ]
 ....: 
Out[26]: 
 date1      date2  date1_year  date2_month date1_next    months_between
0   2013-01-15 2015-02-15        2013            2 2013-02-01  <25 * MonthEnds>
1   2013-01-15 2015-02-15        2013            2 2013-02-01  <25 * MonthEnds>
2   2013-01-15 2015-02-15        2013            2 2013-02-01  <25 * MonthEnds>
3   2013-01-15 2015-02-15        2013            2 2013-02-01  <25 * MonthEnds>
4   2013-01-15 2015-02-15        2013            2 2013-02-01  <25 * MonthEnds>
..         ...        ...         ...          ...        ...               ...
239 2013-01-15 2015-02-15        2013            2 2013-02-01  <25 * MonthEnds>
240 2013-01-15 2015-02-15        2013            2 2013-02-01  <25 * MonthEnds>
241 2013-01-15 2015-02-15        2013            2 2013-02-01  <25 * MonthEnds>
242 2013-01-15 2015-02-15        2013            2 2013-02-01  <25 * MonthEnds>
243 2013-01-15 2015-02-15        2013            2 2013-02-01  <25 * MonthEnds>
[244 rows x 6 columns] 

查看时间序列/日期功能以获取更多详细信息。

列的选择

在电子表格中,您可以通过以下方式选择要选择的列:

由于电子表格列通常在标题行中命名,所以重命名列只是简单地更改该第一个单元格中的文本。

pandas 中使用相同的操作如下所示。

保留某些列
In [27]: tips[["sex", "total_bill", "tip"]]
Out[27]: 
 sex  total_bill   tip
0    Female       14.99  1.01
1      Male        8.34  1.66
2      Male       19.01  3.50
3      Male       21.68  3.31
4    Female       22.59  3.61
..      ...         ...   ...
239    Male       27.03  5.92
240  Female       25.18  2.00
241    Male       20.67  2.00
242    Male       15.82  1.75
243  Female       16.78  3.00
[244 rows x 3 columns] 
删除列
In [28]: tips.drop("sex", axis=1)
Out[28]: 
 total_bill   tip smoker   day    time  size
0         14.99  1.01     No   Sun  Dinner     2
1          8.34  1.66     No   Sun  Dinner     3
2         19.01  3.50     No   Sun  Dinner     3
3         21.68  3.31     No   Sun  Dinner     2
4         22.59  3.61     No   Sun  Dinner     4
..          ...   ...    ...   ...     ...   ...
239       27.03  5.92     No   Sat  Dinner     3
240       25.18  2.00    Yes   Sat  Dinner     2
241       20.67  2.00    Yes   Sat  Dinner     2
242       15.82  1.75     No   Sat  Dinner     2
243       16.78  3.00     No  Thur  Dinner     2
[244 rows x 6 columns] 
重命名列
In [29]: tips.rename(columns={"total_bill": "total_bill_2"})
Out[29]: 
 total_bill_2   tip     sex smoker   day    time  size
0           14.99  1.01  Female     No   Sun  Dinner     2
1            8.34  1.66    Male     No   Sun  Dinner     3
2           19.01  3.50    Male     No   Sun  Dinner     3
3           21.68  3.31    Male     No   Sun  Dinner     2
4           22.59  3.61  Female     No   Sun  Dinner     4
..            ...   ...     ...    ...   ...     ...   ...
239         27.03  5.92    Male     No   Sat  Dinner     3
240         25.18  2.00  Female    Yes   Sat  Dinner     2
241         20.67  2.00    Male    Yes   Sat  Dinner     2
242         15.82  1.75    Male     No   Sat  Dinner     2
243         16.78  3.00  Female     No  Thur  Dinner     2
[244 rows x 7 columns] 

按值排序

在电子表格中进行排序是通过排序对话框完成的。

pandas 有一个DataFrame.sort_values()方法,它接受要按列排序的列列表。

In [30]: tips = tips.sort_values(["sex", "total_bill"])
In [31]: tips
Out[31]: 
 total_bill    tip     sex smoker   day    time  size
67         1.07   1.00  Female    Yes   Sat  Dinner     1
92         3.75   1.00  Female    Yes   Fri  Dinner     2
111        5.25   1.00  Female     No   Sat  Dinner     1
145        6.35   1.50  Female     No  Thur   Lunch     2
135        6.51   1.25  Female     No  Thur   Lunch     2
..          ...    ...     ...    ...   ...     ...   ...
182       43.35   3.50    Male    Yes   Sun  Dinner     3
156       46.17   5.00    Male     No   Sun  Dinner     6
59        46.27   6.73    Male     No   Sat  Dinner     4
212       46.33   9.00    Male     No   Sat  Dinner     4
170       48.81  10.00    Male    Yes   Sat  Dinner     3
[244 rows x 7 columns] 

字符串处理

查找字符串的长度

在电子表格中,可以使用LEN函数找到文本中的字符数。这可以与TRIM函数一起使用以删除额外的空格。

=LEN(TRIM(A2)) 
• 1

您可以使用Series.str.len()找到字符字符串的长度。在 Python 3 中,所有字符串都是 Unicode 字符串。len包括尾随空格。使用lenrstrip排除尾随空格。

In [32]: tips["time"].str.len()
Out[32]: 
67     6
92     6
111    6
145    5
135    5
 ..
182    6
156    6
59     6
212    6
170    6
Name: time, Length: 244, dtype: int64
In [33]: tips["time"].str.rstrip().str.len()
Out[33]: 
67     6
92     6
111    6
145    5
135    5
 ..
182    6
156    6
59     6
212    6
170    6
Name: time, Length: 244, dtype: int64 

请注意,这仍将包括字符串中的多个空格,因此不是 100%等效。

查找子串的位置

FIND电子表格函数返回子字符串的位置,第一个字符为1

您可以使用Series.str.find()方法在字符串列中查找字符的位置。find搜索子字符串的第一个位置。如果找到子字符串,则该方法返回其位置。如果未找到,则返回-1。请记住,Python 索引是从零开始的。

In [34]: tips["sex"].str.find("ale")
Out[34]: 
67     3
92     3
111    3
145    3
135    3
 ..
182    1
156    1
59     1
212    1
170    1
Name: sex, Length: 244, dtype: int64 

根据位置提取子串

电子表格中有一个MID公式,用于从给定位置提取子串。要获取第一个字符:

=MID(A2,1,1) 
• 1

使用 pandas,您可以使用[]符号根据位置提取字符串中的子串。请记住,Python 索引是从零开始的。

In [35]: tips["sex"].str[0:1]
Out[35]: 
67     F
92     F
111    F
145    F
135    F
 ..
182    M
156    M
59     M
212    M
170    M
Name: sex, Length: 244, dtype: object 

提取第 n 个单词

在 Excel 中,您可能会使用文本分列向导来拆分文本并检索特定列。(注意也可以通过公式来实现。)

在 pandas 中提取单词的最简单方法是通过空格拆分字符串,然后按索引引用单词。注意,如果需要的话,还有更强大的方法。

In [36]: firstlast = pd.DataFrame({"String": ["John Smith", "Jane Cook"]})
In [37]: firstlast["First_Name"] = firstlast["String"].str.split(" ", expand=True)[0]
In [38]: firstlast["Last_Name"] = firstlast["String"].str.rsplit(" ", expand=True)[1]
In [39]: firstlast
Out[39]: 
 String First_Name Last_Name
0  John Smith       John     Smith
1   Jane Cook       Jane      Cook 

更改大小写

电子表格提供UPPER、LOWER 和 PROPER 函数,分别用于将文本转换为大写、小写和首字母大写。

等效的 pandas 方法分别是Series.str.upper()Series.str.lower()Series.str.title()

In [40]: firstlast = pd.DataFrame({"string": ["John Smith", "Jane Cook"]})
In [41]: firstlast["upper"] = firstlast["string"].str.upper()
In [42]: firstlast["lower"] = firstlast["string"].str.lower()
In [43]: firstlast["title"] = firstlast["string"].str.title()
In [44]: firstlast
Out[44]: 
 string       upper       lower       title
0  John Smith  JOHN SMITH  john smith  John Smith
1   Jane Cook   JANE COOK   jane cook   Jane Cook 

合并

下面的表将用于合并示例:

In [45]: df1 = pd.DataFrame({"key": ["A", "B", "C", "D"], "value": np.random.randn(4)})
In [46]: df1
Out[46]: 
 key     value
0   A  0.469112
1   B -0.282863
2   C -1.509059
3   D -1.135632
In [47]: df2 = pd.DataFrame({"key": ["B", "D", "D", "E"], "value": np.random.randn(4)})
In [48]: df2
Out[48]: 
 key     value
0   B  1.212112
1   D -0.173215
2   D  0.119209
3   E -1.044236 

在 Excel 中,可以通过 VLOOKUP 合并表格

pandas 数据帧有一个merge()方法,提供类似的功能。数据不需要提前排序,并且不同的连接类型通过how关键字实现。

In [49]: inner_join = df1.merge(df2, on=["key"], how="inner")
In [50]: inner_join
Out[50]: 
 key   value_x   value_y
0   B -0.282863  1.212112
1   D -1.135632 -0.173215
2   D -1.135632  0.119209
In [51]: left_join = df1.merge(df2, on=["key"], how="left")
In [52]: left_join
Out[52]: 
 key   value_x   value_y
0   A  0.469112       NaN
1   B -0.282863  1.212112
2   C -1.509059       NaN
3   D -1.135632 -0.173215
4   D -1.135632  0.119209
In [53]: right_join = df1.merge(df2, on=["key"], how="right")
In [54]: right_join
Out[54]: 
 key   value_x   value_y
0   B -0.282863  1.212112
1   D -1.135632 -0.173215
2   D -1.135632  0.119209
3   E       NaN -1.044236
In [55]: outer_join = df1.merge(df2, on=["key"], how="outer")
In [56]: outer_join
Out[56]: 
 key   value_x   value_y
0   A  0.469112       NaN
1   B -0.282863  1.212112
2   C -1.509059       NaN
3   D -1.135632 -0.173215
4   D -1.135632  0.119209
5   E       NaN -1.044236 

merge相对于VLOOKUP有一些优势:

  • 查找值不需要是查找表的第一列
  • 如果匹配了多行,则每个匹配都会有一行,而不仅仅是第一个
  • 它将包括查找表中的所有列,而不仅仅是单个指定的列
  • 它支持更复杂的连接操作

Pandas 2.2 中文官方教程和指南(四)(3)https://developer.aliyun.com/article/1509882

相关文章
|
9天前
|
SQL 数据采集 数据挖掘
Pandas 教程
10月更文挑战第25天
21 2
|
3月前
|
存储 JSON 数据格式
Pandas 使用教程 CSV - CSV 转 JSON
Pandas 使用教程 CSV - CSV 转 JSON
33 0
|
3月前
|
JSON 数据格式 Python
Pandas 使用教程 JSON
Pandas 使用教程 JSON
39 0
|
3月前
|
SQL 数据采集 JSON
Pandas 使用教程 Series、DataFrame
Pandas 使用教程 Series、DataFrame
55 0
|
5月前
|
数据采集 存储 数据可视化
Pandas高级教程:数据清洗、转换与分析
Pandas是Python的数据分析库,提供Series和DataFrame数据结构及数据分析工具,便于数据清洗、转换和分析。本教程涵盖Pandas在数据清洗(如缺失值、重复值和异常值处理)、转换(数据类型转换和重塑)和分析(如描述性统计、分组聚合和可视化)的应用。通过学习Pandas,用户能更高效地处理和理解数据,为数据分析任务打下基础。
585 3
|
6月前
|
存储 SQL 索引
Pandas 2.2 中文官方教程和指南(十一·二)(4)
Pandas 2.2 中文官方教程和指南(十一·二)
61 1
|
6月前
|
测试技术 索引 Python
Pandas 2.2 中文官方教程和指南(十一·二)(3)
Pandas 2.2 中文官方教程和指南(十一·二)
49 1
|
6月前
|
索引 Python
Pandas 2.2 中文官方教程和指南(十一·二)(2)
Pandas 2.2 中文官方教程和指南(十一·二)
47 1
|
6月前
|
索引 Python
Pandas 2.2 中文官方教程和指南(一)(4)
Pandas 2.2 中文官方教程和指南(一)
55 0
|
6月前
|
存储 SQL JSON
Pandas 2.2 中文官方教程和指南(一)(3)
Pandas 2.2 中文官方教程和指南(一)
92 0
下一篇
无影云桌面