当许多人开始踏足数据分析领域时,他们常常会对选择何种工具感到迷茫。在这个充满各种选项的时代,为什么会有这么多人选择 Pandas 作为他们的数据分析工具呢?这个问题似乎简单,但背后涉及了许多关键因素。在探究这个问题之前,让我们先理解一下 Pandas 的背景和特点。
优化的数据结构:Pandas提供了几种高效的数据结构,如DataFrame和Series,它们是为了优化数值计算和数据操作而设计的。这些数据结构在内存中以连续块的方式存储数据,有助于提高数据访问速度。
DataFrame的一列就是Series,Series可以转化为DataFrame,调用方法函数to_frame()即可
Series 是 pandas 中的一种数据结构,可以看作是带有标签的一维数组。它由两部分组成:索引(Index) 和 值(Values)。
- 索引(Index): 索引是用于标识每个元素的标签,可以是整数、字符串、日期等类型的数据。索引提供了对 Series 中数据的标签化访问方式。
- 值(Values): 值是 Series 中存储的实际数据,可以是任何数据类型,如整数、浮点数、字符串等。
底层使用C语言:Pandas的许多内部操作都是用Cython或C语言编写的,Cython是一种Python的超集,它允许将Python代码转换为C语言代码,从而提高执行效率。
向量化操作:Pandas支持向量化操作,这意味着可以对整个数据集执行单个操作,而不是逐行或逐列地进行迭代。向量化操作通常比纯Python循环更快,因为它们可以利用底层的优化和硬件加速。
利用内置函数:Pandas广泛使用内置函数来执行常见的数据处理任务,如排序、分组和聚合。这些函数通常经过高度优化,能够快速处理大量数据。
了解完这些,接下来,让我们一起探索 Pandas 中那些不可或缺的常用函数,掌握数据分析的关键技能。
①.map() 函数
用于根据传入的字典或函数,对 Series 中的每个元素进行映射或转换。
具体来说,map()
函数可以接受一个字典或一个函数作为参数,然后根据这个字典或函数对 Series 中的每个元素进行映射或转换,生成一个新的 Series,并返回该 Series。
如果传入的是一个字典,则 map()
函数将会使用字典中键对应的值来替换 Series 中的元素。如果传入的是一个函数,则 map() 函数将会使用该函数对 Series 中的每个元素进行转换。
举个例子
import pandas as pd
# 创建一个 Series
s = pd.Series(['apple', 'banana', 'cherry'])
# 定义一个字典,用于替换元素
replacement_dict = {'apple': 'red', 'banana': 'yellow', 'cherry': 'red'}
# 使用 map() 函数根据字典替换元素
s_mapped = s.map(replacement_dict)
print(s_mapped)
运行结果
0 red
1 yellow
2 red
dtype: object
②.fillna()函数
fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None, **kwargs)
参数:
- value:用于填充的空值的值。
- method: {‘backfill’, ‘bfill’, ‘pad’, ‘ffill’, None}, 默认为 None。定义了填充空值的方法, pad / ffill表示用前面行/列的值,填充当前行/列的空值; backfill / bfill表示用后面行/列的值,填充当前行/列的空值。
- axis:轴。0或’index’,表示按行删除;1或’columns’,表示按列删除。
- inplace:是否原地替换。布尔值,默认为False。如果为True,则在原DataFrame上进行操作,返回值为None。
- limit:int, default None。如果method被指定,对于连续的空值,这段连续区域,最多填充前 limit 个空值(如果存在多段连续区域,每段最多填充前 limit 个空值)。如果method未被指定, 在该axis下,最多填充前 limit 个空值(不论空值连续区间是否间断)
- downcast:dict, default is None,字典中的项为,为类型向下转换规则。或者为字符串“infer”,此时会在合适的等价类型之间进行向下转换,比如float64 to int64 if possible。
举个例子一 传入字典
import pandas as pd
# 创建一个 DataFrame
df = pd.DataFrame({'A': [1, 2, None, 4],
'B': ['a', 'b', None, 'd']})
# 使用 fillna() 方法填充缺失值,指定不同的填充值
filled_df = df.fillna({'A': 0, 'B': '填充值'})
print("填充指定值的结果:")
print(filled_df)
运行结果
填充指定值的结果:
A B
0 1.0 a
1 2.0 b
2 0.0 填充值
3 4.0 d
例子二 传入值
import pandas as pd
# 创建一个 DataFrame
df = pd.DataFrame({'A': [1, 2, None, 4],
'B': ['a', 'b', None, 'd']})
# 使用 fillna() 方法填充缺失值,不指定填充值,默认使用 NaN
default_filled_df = df.fillna("test")
运行结果
A B
0 1 a
1 2 b
2 test test
3 4 d
③.extend() 函数,将一个可迭代对象的所有元素添加到列表的末尾。
举个例子
# 创建一个列表
list1 = [1, 2, 3]
# 创建另一个列表
list2 = [4, 5, 6]
# 使用 extend() 方法将 list2 扩展到 list1
list1.extend(list2)
print(list1) # 输出: [1, 2, 3, 4, 5, 6]
# 创建一个列表
list1 = [1, 2, 3]
# 创建一个字典
dict1 = {'a': 10, 'b': 20, 'c': 30}
# 使用 extend() 方法将 dict1 的键扩展到 list1
list1.extend(dict1)
print(list1) # 输出: [1, 2, 3, 'a', 'b', 'c']
④.df.index.difference(null_ind) 查找两个索引的集合差异
举个例子
import pandas as pd
# 创建两个索引对象
index1 = pd.Index([1, 2, 3, 4])
index2 = pd.Index([3, 4, 5, 6])
# 使用 difference() 方法获取两个索引对象之间的差异
index_difference = index1.difference(index2)
print("两个索引对象之间的差异:")
print(index_difference)
运行结果
两个索引对象之间的差异:
Int64Index([1, 2], dtype='int64')
⑤.astype() 方法用于将 Series 的数据类型转换为指定的数据类型
举个例子
import pandas as pd
# 创建一个 Series
s = pd.Series([1, 2, 3, 4])
# 使用 astype() 方法将 Series 的数据类型转换为字符串类型
s_str = s.astype(str)
print("转换数据类型后的 Series:")
print(s_str)
运行结果
转换数据类型后的 Series:
0 1
1 2
2 3
3 4
dtype: object
⑥.pd.cut()函数
将连续性数值进行离散化处理:如对年龄、消费金额等进行分组
pandas.cut(x, bins, right=True, labels=None, retbins=False, precision=3, include_lowest=False, duplicates='raise', ordered=True)
重点说下
bins :整数,标量序列或者间隔索引,是进行分组的依据,
- 如果填入整数n,则表示将x中的数值分成等宽的n份(即每一组内的最大值与最小值之差约相等);
- 如果是标量序列,序列中的数值表示用来分档的分界值
- 如果是间隔索引,“ bins”的间隔索引必须不重叠
举个例子
import pandas as pd
# 创建一个 Series
s = pd.Series([10, 20, 30, 40, 50])
# 使用 pd.cut() 函数将数据划分为三个区间
bins = [0, 30, 40, 100] # 区间边界
labels = ['低', '中', '高'] # 区间标签
categories = pd.cut(s, bins=bins, labels=labels)
print("划分区间后的结果:")
print(categories)
运行结果
划分区间后的结果:
0 低
1 低
2 低
3 中
4 高
dtype: category
Categories (3, object): ['低' < '中' < '高']
import pandas as pd
# 创建一个简单的DataFrame
df = pd.DataFrame({
'A': [1, 2, 3, 4, 5],
'B': [5, 4, 3, 2, 1]
})
# 查找列'A'中大于3的所有行,并将结果转换为64位整数
result = (df['A'] > 3).astype('int64')
print(result)
-- 打印结果
0 0
1 0
2 0
3 1
4 1
dtype: int64
⑦.pd.merge()
pd.merge(left, right, how = 'inner', on = None, left_on = None, right_on = None,
left_index = False, right_index = False, sort = True, suffixes = ('_x','_y'),
copy = True, indicator = False, validate = None)
参数
- left、right:需要连接的两个DataFrame或Series,一左一右
- how:两个数据连接方式,默认为inner,可设置inner、outer、left或right
- on:作为连接键的字段,左右数据中都必须存在,否则需要用left_on和right_on来指定
- left_on:左表的连接键字段
- right_on:右表的连接键字段
- left_index:为True时将左表的索引作为连接键,默认为False
- right_index:为True时将右表的索引作为连接键,默认为False
- suffixes:如果左右数据出现重复列,新数据表头会用此后缀进行区分,默认为_x和_y
举个例子
import pandas as pd
# 创建两个 DataFrame
df1 = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
df2 = pd.DataFrame({'A': [1, 2, 3], 'C': [7, 8, 9]})
# 使用 pd.merge() 函数根据 'A' 列合并两个 DataFrame
merged_df = pd.merge(df1, df2, on='A')
print("合并后的 DataFrame:")
print(merged_df)
运行结果
合并后的 DataFrame:
A B C
0 1 4 7
1 2 5 8
2 3 6 9
在本文中,我们深入探讨了Pandas库中一系列高效的数据处理方法。这些方法不仅极大地简化了数据处理的复杂性,而且提供了强大的功能集,使得数据分析工作更为高效和灵活。我们从基础的Series和DataFrame结构出发,逐步深入到数据的清洗、转换和处理技巧,掌握了一套能够应对多样化数据分析任务的工具箱。尽管本文仅触及了Pandas强大功能的表面,但其广阔的应用领域和深邃的技术内涵仍待我们进一步挖掘和学习。