Python交互式学习-Pandas(上)

目录

一、Pandas简介

Pandas 是什么 

Pandas安装

Pandas 和 Numpy 的差别

总结

二、基本操作

从文件读取数据

Pandas中的数据是什么

数据序列Series

数据表DataFrame

总结

选取数据

多种选取方式

选Column

loc 

iloc 

loc和iloc混搭 

条件过滤筛选 

 Series和DataFrame类似

总结 


一、Pandas简介

大数据虽然描述的是海量的数据,但是大数据离你却并不远,特别是大数据所涵盖的技术,在你生活当中,是时刻都能使用这些大数据涉及到的技术, 来解决你生活中的具体问题。

  • 办公自动化
    • 上学上班,有 Excel 或者格式化的文本文件,需要进行数据加工处理
    • 对大量的这些文本文件作图,想要自动化处理
  • 人工智能
    • 数据分析,可视化数据规律
    • 数据前处理,为 AI 模型展平道路

Pandas 是什么 

简单来说,Pandas 是 Python 中一个比较常用的第三方库,里面集成了很多和数据相关的功能组件。上面提到的那些场景中, 无非就是要:

  1. 处理数据
  2. 分析数据
  3. 画图

所以 Pandas 就围绕着这些环节施展能力。而且它承接了 Numpy 的能力,使用的底层也是 Numpy。按理来说,我们也能用 Numpy 来实现上述功能。

Pandas安装

cmd:pip install Pandas

Pandas 和 Numpy 的差别

Pandas 是在 Numpy 上的封装。 继承了 Numpy 的所有优点,但是这种封装有好有坏,我们在这节内容中就先来阐述一下 Pandas 和 Numpy 的对比

类比 Python

用过 Python,你肯定熟悉里面的 List和Dictionary, 我比较常拿这两种形态来对比 Numpy 和 Pandas 的关系

a_list = [1,2,3]
a_dict = {"a": 1, "b": 2, "c": 3}
print("list:", a_list)
print("dict:", a_dict)

上面就是一种最常见的 Python 列表和字典表达方式。而下面,我们展示的就是 Numpy 和 Pandas 的一种构建方式

import pandas as pd
import numpy as np

a_array = np.array([
    [1,2],
    [3,4]
])
a_df = pd.DataFrame(
    {"a": [1,3], 
     "b": [2,4]}
)

print("numpy array:\n", a_array)
print("\npandas df:\n", a_df)

你会发现,我们看到的结果中,Numpy 的是没有任何数据标签信息的,你可以认为它是纯数据。而 Pandas 就像字典一样,还记录着数据的外围信息, 比如标签(Column 名)和索引(Row index)。 这也是我为什么总说 Numpy 是 Python 里的列表,而 Pandas 是 Python 里的字典

还是回到之前提的问题,对于数据运算,既然我们有了 Numpy,为什么还要用 Pandas?。对比列表和字典,我们很容易感受到其中的一种原因。 就是 Pandas 帮我们记录的信息量变多了

在Numpy中,如果你不特别在其他地方标注,你是不清楚记录的这里边记录的是什么信息的。Pandas 记录的信息可以特别丰富, 你给别人使用传播数据的时,这些信息也会一起传递过去。或者你自己处理数据时对照着信息来加工数据,也会更加友善。

这就是在我看来 Pandas 对比 Numpy 的一个最直观的好处。

另外 Pandas 用于处理数据的功能也比较多,信息种类也更丰富,特别是你有一些包含字符的表格,Pandas 可以帮你处理分析这些字符型的数据表。 当然还有很多其它功能,比如处理丢失信息,多种合并数据方式,读取和保存为更可读的形式等等。

这些都让 Pandas 绽放光彩  但是,Pandas 也有不足的地方:运算速度稍微比 Numpy 慢

你想想,因为 Pandas 是在 Numpy 之上的一层封装,所以肯定在处理数据的时候要多几层处理,小数据量的处理不要紧,慢一点就慢一点, 你也感受不到处理速度的变化。但当数据量变大,用 Numpy 要处理 1 小时的数据,你可能用 Pandas 要花两小时。 所以你得依据自己的实际需求来选择到底是用 Numpy 还是 Pandas。

如果在做少量数据的分析时,因为不涉及到机器学习的模型运算等,我都可以用 Pandas,但如果要模型训练, 训练过程中还一直要调用数据处理的功能, 我肯定毫不犹豫都用 Numpy 来做

总结

Pandas 是 Numpy 的封装库,继承了 Numpy 的很多优良传统,也具备丰富的功能组件,但是你还是得分情况来酌情选择要使用的工具

二、基本操作

从文件读取数据

  • Excel文件
    • pd.read_excel()
    • df.to_excel()
  • csv或txt等纯文本文件
    • pd.read_csv()
    • df.to_csv()
  • 其他
    • pd.read_clipboard()
    • pd.read_html()

Pandas中的数据是什么

简单来说,Pandas 支持最好的是一维和二维数据,一维数据就是一个序列,一条数据,而二维数据是我们生活中更常见的种类,基本上所有 Excel 数据, 都是二维数据,有横纵交替,用两个维度来定位这个数据

  • 数据序列Series
    • 创建
    • 转换 Numpy
  • 数据表DataFrame
    • 创建
    • 转换 Numpy

数据序列Series

一串 Python List 的形式你肯定不陌生,Pandas 中的 Series 的核心其实就是一串类似于 Python List 的序列。只是它要比 Python List 丰富很多, 有更多的功能属性

import pandas as pd

l = [11,22,33]
s = pd.Series(l)
print("list:", l)
print("series:", s)

打印出来,对比很明显,Pandas Series 还帮我们额外维护了一份索引。有这个索引有啥意义呢?Python List 不也有一个隐藏的序号索引吗? 其实啊,Pandas 之所以做这一种索引,目的并不是仅让你用 0123 这样的序号来检索数据,它还想让你可以用自己喜欢的索引来检索。看看下面的代码吧

s = pd.Series(l, index=["a", "b", "c"])

只要是有索引形式的结构,都可以搞成 Series?比如下面这样

s = pd.Series({"a": 11, "b": 22, "c": 33})

既然 Python 的 List 可以用来创建 Series,那我想 Numpy 应该也可以吧,要不来试试

import numpy as np

s = pd.Series(np.random.rand(3), index=["a", "b", "c"])

既然 Numpy 和 List 可以用来创建 Series,那 Series 能回退到 Numpy array 或者 List 吗? 我们试一试

print("array:", s.to_numpy())
print("list:", s.values.tolist())

还真是,他们真的能自由穿梭,这可大大减轻了我们在不同的数据形式中切换的成本 

数据表DataFrame

Pandas 首先支持的是序列数据和表格数据,因为这两种是如常生活中最常用的数据保存和编辑格式了,你见过有人去编辑一个 3 维数据吗? 话说回来,如果你硬扯上 Excel 里面的不同 sheet,把 sheet 当成第三个维度,那也是成立的。sheet 这个我就先不说了,我们先看看用 Pandas 的 DataFrame 怎么维护一张数据表吧。

举个最简单的例子。将一个二维数组变成 Pandas 的 DataFrame

df = pd.DataFrame([
  [1,2],
  [3,4]
])
df

它创建出来的 df,在真实数据外圈,还包上了一层其他的数据,比如 0 1, 这是什么呢?其实这是 DataFrame 中,用来索引行列的序号, 外圈的横竖都是 0 1 代表着每个维度上,都有第 0 位和第 1 位。如果我要按位置来选取一下其中的值,我可以这么干

# 第 0 行,第 1 列
# 或 第一个维度中的第 0 号,第二个维度中的第 1 号
df.at[0, 1]  

上面我们见识到了直接用一个二维列表来创建 DataFrame,但是自动创建的索引序号并不是很可读。我们还能将这些序号换成人类更好理解的文字标签信息

df = pd.DataFrame({"col1": [1,3], "col2": [2, 4]})
df

可以从结果看出,其实字典中的 key 会被当成是数据中的 column,而 value 会被当做是 row,这个非常符合你在 Excel 中的使用习惯。 因为往往随着数据量变大,你用鼠标滚轮滚动查看不同数据的时候,天然的比较喜欢上下查看不同的数据样本,而不是左右查看,所以一般都是左右记的是数据标签(特征), 上下排列的是不同数据样本 

见识了字典变 DataFrame,其实 Series 也是可以组合变成 DataFrame 的,而且这也非常符合常理, 如果我从 DataFrame 中取出一个 Column, 这不就变成了一条 Series 了吗?

print(df["col1"], "\n")
print("取出来之后的 type:", type(df["col1"]))

那么将两个 Series 拼接起来呢

df = pd.DataFrame({"col1": pd.Series([1,3]), "col2": pd.Series([2, 4])})
df

前面 Series 说过,我们是可以为它构建特殊索引的,现在来看看 Series 和 DataFrame 构建索引的方式:

s = pd.Series([1.0, 2.0, 3.0], index=["a", "b", "c"])
df = pd.DataFrame({"col1": [1,3], "col2": [2, 4]}, index=["a", "b"])
print(s, "\n")
print(df)

既然 DataFrame 的 Column 和 Index 这么有意思,十有八九,你会想取出来用一用这些 Column 和 Index,比如你数据比较大的时候,想初步看看这份数据涉及了多少特征, 数据的 index 有多少种的时候,你可以直接获取到这些信息 

print(df.index, "\n")
print(df.columns)

现在有了 Pandas 中的 DataFrame,我们可以转化成 Numpy 

df = pd.DataFrame({"col1": [1,3], "col2": [2, 4]}, index=["a", "b"])
df.to_numpy()

总结

Pandas 中,为了我们提供了日常最常用的数据存储方式,分别是 Series 的一维数据,和 DataFrame 的二维数据,在机器学习中,我们常会接触到 3 维甚至是更高维度, 但是在分析数据的时候,特别是,要结合 Excel 来分析数据的时候,二维数据才是最常用的。

选取数据

多种选取方式

在 Pandas 中,有丰富的选取数据方式,这可比 List,Dictionary,甚至是 Numpy 还要多样化。我们既能通过文字标签来定位数据,也能通过数值序号来定位。 所以为了实现这种多样性,Pandas 对于数据的选取采用了不同类型的处理方法,比如 .loc.iloc 等

 面对应用比较多的工作学习场景,我先以 Excel 型的表格数据举例,请你帮我构建一下下面这份 DataFrame

import pandas as pd
import numpy as np

data = np.arange(-12, 12).reshape((6, 4))
df = pd.DataFrame(
  data, 
  index=list("abcdef"), 
  columns=list("ABCD"))
d

选Column

 “Column”(列)通常指的是数据表格或数据框(DataFrame)中的一个垂直字段。每列包含了与某一特定变量或特征相关的数据

看到了上面这份数据后,我们发现,DataFrame 会分 Column 和 Row(index)。如果你搞机器学习,通常我们的 Column 是特征,Row 是数据样本, 在要对某个特征进行分析的时候,比如要做特征数值分布的分析,我们得把特征取出来吧

df["B"]

多个特征

print("numpy:\n", data[:, [2,1]])
print("\ndf:\n", df[["C", "B"]])

已经能选 column 了,那意味着肯定能将 Index(Row)的信息也一起考虑到数据筛选的工作当中了

loc 

pandas 库中,.loc 是一个属性,用于通过标签(即行标签和列标签)进行数据选择和切片操作。它允许你根据行和列的标签来访问 DataFrame 或 Series 中的数据

如果你是刚从 面向 Excel 编程,或者也没怎么用过 Excel 中的函数的朋友,也可以轻松从 loc 函数中找到一丝丝熟悉的感觉。 因为这个 .loc 方法是更贴近我们人类直觉的,按照字面来选取数据块的方式。

在 Numpy 中选取数据一般都是按照在维度上的排序来定位的。 比如对于你刚刚创建的 Numpy 数据data

data[2:3, 1:3]

而在 DataFrame 中,同样是上述功能,你可以这么干 

df.loc["c":"d", "B":"D"]

除了筛选一个片段,还可以像 Numpy 那样单个单个的选取 

print("numpy:\n", data[[3,1], :])
print("\ndf:\n", df.loc[["d", "b"], :])

iloc 

pandas 库中,.iloc 是一个用于基于位置(即整数位置)进行数据选择和切片的属性。它允许你通过行和列的位置(而不是标签)来访问 DataFrame 或 Series 中的数据

看完面向 Excel 编程,我们再来回到编程本身,用程序的思维去选取数据。这意味着什么?用最朴素的方法,也是意味着能更快找到数据位置,比如直接用位置信息来筛选。 Numpy 不就是这么干的吗?这时 .iloc 功能就派上用场了

同样还是上面那份数据,我们走一遍 .iloc 的流程

print("numpy:\n", data[2:3, 1:3])
print("\ndf:\n", df.iloc[2:3, 1:3])

简直和 Numpy 的模式一模一样,就是结果中多了一个 DataFrame 的标签信息

print("numpy:\n", data[[3,1], :])
print("\ndf:\n", df.iloc[[3, 1], :])

loc和iloc混搭 

难免有时候,我们需要混搭 loc 和 iloc 的方式,比如我想要选取第 2 到第 4 位数据的 A C 两个特征,这时咋办? 想想 Pandas 这么牛逼,肯定有办法解决。的确,它解决的方法是采用索引转换的方式,比如我在 .loc 模式下,将序号索引转换成 .loc 的标签索引

row_labels = df.index[2:4]
print("row_labels:\n", row_labels)
print("\ndf:\n", df.loc[row_labels, ["A", "C"]])

再看看 Column 的 labels 怎么取

col_labels = df.columns[[0, 3]]
print("col_labels:\n", col_labels)
print("\ndf:\n", df.loc[row_labels, col_labels]

用 df.index 和 df.columns 来调取到全部的标签,然后在用像 Numpy index 索引的方式把这些标签给筛选出来,放到 .loc 里面用。 那反过来,我想要找 A B 两个特征的 前两个数据

col_index = df.columns.get_indexer(["A", "B"])
print("col_index:\n", col_index)
print("\ndf:\n", df.iloc[:2, col_index])

同理,df.index.get_indexer(["a", "b"]) 也可以这样获取到 label 对应的 index 信息 

条件过滤筛选 

 选在 A Column 中小于 0 的那些数据

df[df["A"] < 0

选在第一行数据不小于 -10 的数据,这里注意了你可以用两种方式,一种是 ~ 来表示  什么什么,第二种是直接用 >=-10 来筛选 

print("~:\n", df.loc[:, ~(df.iloc[0] < -10)])
print("\n>=:\n", df.loc[:, df.iloc[0] >= -10])

同上面类似的,我还能用或 | 来表示 or 的意思, & 表述 and

比如选在第一行数据不小于 -10 或小于 -11 的数据 

i0 = df.iloc[0]
df.loc[:, ~(i0 < -10) | (i0 < -11)]

你可以用 .loc 或者 .iloc 来做过滤处理。然后用 .loc 来做筛选。为什么用 .iloc 来筛选呢,比如下面这样

df.iloc[:, ~(df.iloc[0] < -10)]

 这样写居然会导致报错,为什么呢?你分析分析,把 ~(df.iloc[0] < -10) 这个筛选条件打印出来看看它是什么值。然后想一想 .iloc 能够接受的值是啥? 想清楚了,这个问题就迎刃而解了

在使用 pandas.iloc 时,表达式 df.iloc[:, ~(df.iloc[0] < -10)] 的目的是通过布尔索引来选择列。让我们逐步解析这个表达式的含义:

  1. df.iloc[0] < -10

    • 这个表达式会返回一个布尔 Series,表示 DataFrame 中第一行(即索引为 0 的行)的每个元素是否小于 -10。
    • 例如,如果第一行的数据是 [5, -20, -15],则这个条件会生成一个布尔 Series [False, True, True]
  2. ~(df.iloc[0] < -10)

    • ~ 是按位取反操作符。在布尔 Series 上应用 ~ 操作符会将 True 变为 False,将 False 变为 True
    • 例如,布尔 Series [False, True, True] 经 ~ 操作符处理后,会变为 [True, False, False]
  3. df.iloc[:, ~(df.iloc[0] < -10)]

    • 这个表达式通过 .iloc 选择 DataFrame 的列,其中列的选择是基于上一步生成的布尔 Series。
    • ~(df.iloc[0] < -10) 生成的布尔 Series [True, False, False] 表示要选择那些对应于 True 的列,即 DataFrame 中的列 0(因为 True 表示选择)会被保留下来,列 1 和 2 会被排除。

表达式 df.iloc[:, ~(df.iloc[0] < -10)] 选择了 DataFrame 中那些在第一行不满足小于 -10 条件的列。这是通过布尔索引和 .iloc 结合使用来实现的 

 Series和DataFrame类似

import pandas as pd

list_data = list(range(-4, 4))
s = pd.Series(
  list_data,
  index=list("abcdefgh"))
# 按标签筛选数据 .loc
print(s.loc[["a", "g", "c"]], "\n")
print(s.loc["c": "f"])
# 按 index 筛选数据 .iloc
print(s.iloc[[3, 1, 5]], "\n")
print(s.iloc[2: 4])
# iloc 和 loc 互相混用
print(s.iloc[s.index.get_indexer(["c", "d"])], "\n")
print(s.loc[s.index[[3,2]]])
# 按条件过滤筛选
print(s.loc[s < 3], "\n")
print(s.loc[(s < 0) & (s > -2)], "\n")
print(s.loc[(s < 0) | (s > 2)], "\n")

总结 

Pandas 的数据筛选方法比 Numpy 丰富多了,介绍的篇幅也有点多,我日常用的最多的还是用条件来筛选,比如在处理机器学习的脏数据的时候,要用很多筛选逻辑。 有时甚至我会觉得 Numpy 的筛选方式不够多,专门把 Numpy 数据转换成 Pandas 数据,然后再用 Pandas 提供的丰富工具处理数据,再转回 Numpy。 相信你用熟了之后,数据处理将要简单很多

  • 15
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值