赞
踩
经过前几篇的基础语法的学习,您已经掌握了Dataframe的基础操作。在掌握基础操作后,进一步探索其进阶用法能够让你更高效地处理和分析数据。
DataFrame的进阶用法涵盖了数据处理、探索、可视化和集成等多个方面。通过深入学习和实践,你将能够更充分地利用DataFrame的功能和优势,提升数据处理和分析的能力,为数据驱动的决策提供有力支持。(可视化将在matpoltlib中详细介绍)
在 Pandas 中,DataFrame 的复合索引(也称为多级索引或层次化索引)允许在多个维度上对数据进行索引。这通常通过使用 MultiIndex 来实现,它可以通过多种方式创建,包括从多个列或数组、从元组列表等。复合索引特别有用于在数据集中表示多个分类变量,并允许进行高级的数据选择和聚合。
下面是一些关于如何在 Pandas 中使用 DataFrame 的复合索引的示例和解释:
可以通过几种方式创建具有复合索引的 DataFrame:
可以从一个现有的 DataFrame 的列中创建复合索引。
代码实现:
import pandas as pd
# 创建一个简单的 DataFrame
df = pd.DataFrame({
'A': ['foo', 'foo', 'foo', 'bar', 'bar'],
'B': ['one', 'one', 'two', 'two', 'one'],
'C': ['small', 'large', 'large', 'small', 'small'],
'D': [1, 2, 2, 3, 3],
'E': [2, 4, 5, 5, 6]
})
# 从列 'A' 和 'B' 创建复合索引
df_multiindex = df.set_index(['A', 'B'])
df_multiindex
运行结果:
在创建 DataFrame 时直接传递一个 MultiIndex。
# 创建多级索引
index = pd.MultiIndex.from_tuples([('foo', 'one'), ('foo', 'two'), ('bar', 'one'), ('bar', 'two')])
# 创建一个简单的 DataFrame,并使用多级索引
df_multiindex = pd.DataFrame({
'C': ['small', 'large', 'large', 'small'],
'D': [1, 2, 2, 3],
'E': [2, 4, 5, 6]
}, index=index)
df_multiindex
运行结果:
有了复合索引,可以使用它们来方便地选择数据。
# 选择索引为 ('foo', 'one') 的行
print(df_multiindex.loc[('foo', 'one')])
# 选择所有 'foo' 行的 'D' 列
print(df_multiindex.loc['foo']['D'])
# 选择 'foo' 下 'one' 和 'two' 的所有行
print(df_multiindex.loc[('foo', slice(None))])
运行结果:
如果不再需要复合索引,或者想要将其转换回普通的列,可以使用 reset_index 方法。
# 重置索引,将复合索引的级别作为普通列添加回 DataFrame
df_reset = df_multiindex.reset_index()
df_reset
运行结果:
复合索引与 groupby 方法结合使用时特别强大,因为它允许基于多个键对数据进行分组。
# 使用复合索引进行分组并计算每组的平均值
grouped = df_multiindex.groupby(level=[0, 1]).mean()
grouped
运行结果:
unstack()函数是用于将一个多级索引(multi-index)的DataFrame或Series从一个层级转换到列中,或者从列中转换到另一个层级。这通常用于数据重塑,使得数据的展现形式更符合分析的需要。
当DataFrame或Series具有一个或多个层级索引时,unstack()函数可以将低层级的索引转换为列标题,同时保持高层级索引作为行索引。反之,如果unstack()函数用于具有多层列标题的DataFrame,则可以将低层级的列标题转换为行索引。
level:整数或字符串,可选参数。指定要解包的层级。如果省略此参数,将解包所有分层。通过指定level,你可以控制将哪一层级的索引横向展开,而其余层级的索引保持不变。
fill_value:可选参数。用于替换缺失值的值。在解包索引的过程中,可能会出现某些位置没有对应数据的情况,此时可以使用fill_value参数来指定一个默认值填充这些缺失位置。
dropna:布尔值,可选参数。指定是否删除那些只包含缺失值的列。当解包索引后,有些列可能全部为缺失值,通过设置dropna=True,可以自动删除这些列,使数据更加整洁。
# 创建一个具有多层索引的 DataFrame
index = pd.MultiIndex.from_product([['A', 'B'], ['one', 'two'], ['x', 'y', 'z']])
data = pd.Series(np.random.randn(12), index=index)
print(data)
df = data.unstack([0, 1])
df
在这个示例中,我们创建了一个具有三层索引的Series对象,并使用unstack([0, 1])将前两层索引转换为列标题。
df #%% # 创建一个具有多层索引的DataFrame arrays = [np.array(['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux']), np.array(['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']), np.array(['small', 'large', 'large', 'small', 'small', 'large', 'large', 'small'])] # 将这些数组转换为MultiIndex index = pd.MultiIndex.from_arrays(arrays, names=('first', 'second', 'third')) # 创建一个简单的DataFrame df = pd.DataFrame(np.random.randn(8, 2), index=index, columns=['A', 'B']) print("原始DataFrame:") print(df) # 使用unstack将'third'层级的索引转换为列 df_unstacked = df.unstack('third') print("\n使用unstack后的DataFrame:") df_unstacked
运行结果:
在这个示例中,我们创建了一个具有三层索引的DataFrame,并使用unstack(‘third’)将第三层索引(‘third’)转换为列。
unstack() 可以用来将分组后的结果从层级索引的形式转换为更宽格式的表格。
# 创建一个示例 DataFrame data = { 'A': ['foo', 'foo', 'foo', 'bar', 'bar'], 'B': ['one', 'one', 'two', 'two', 'one'], 'C': ['small', 'large', 'large', 'small', 'small'], 'D': [1, 2, 2, 3, 3], 'E': [2, 4, 5, 5, 6] } df = pd.DataFrame(data) # 根据 A 和 B 列进行分组,并对 D 列求和 grouped = df.groupby(['A', 'B']).sum() print("分组聚合后的结果:") print(grouped) # 使用 unstack() 将 B 列的层级索引转换为列 unstacked = grouped.unstack('B') print("\n使用 unstack() 后的结果:") print(unstacked)
代码实现:
首先我们先导入数据
import numpy as np
data = pd.read_csv('/export/data/pandas_data/gapminder.tsv',sep='\t')
data
数据样式:
# 求不同洲的平均寿命
data.groupby('continent')['lifeExp'].mean()
运行结果:
# 写法2: df.列名 直接实现.
data.groupby('continent').lifeExp.mean()
运行结果:
这两个函数完全一样, 并无任何区别.
# 写法3: 结合 agg() 或者 aggregate()函数实现, 这两个函数完全一样, 并无任何区别.
data.groupby('continent').lifeExp.agg('mean') # 这个mean是 Pandas中的mean()函数, 要加: 引号包裹
data.groupby('continent').lifeExp.aggregate('mean')
# 上述格式变形写法: {要操作的列1: 聚合函数, 要操作的列2: 聚合函数...}
data.groupby('continent').agg({'lifeExp':'mean'})
data.groupby('continent').aggregate({'lifeExp':'mean'})
# 写法4: 还可以直接传入 numpy包下的 函数.
data.groupby('continent').lifeExp.agg(np.mean) # 这里的np.mean是 Numpy中的mean()函数对象, 不要加引号
data.groupby('continent').agg({'lifeExp': np.mean})
# 写法5: 传入自定义函数, 实现: 计算平均值.
# 1. 自定义函数, 用于计算 某列值 的平均值.
def my_mean(col):
# 该列平均值 = 该列数据和 / 该列数据个数
return col.sum() / col.size # Series中: sum()函数, size: 属性
# 2. groupby分组聚合时, 可以传入: 自定义函数.
data.groupby('continent').lifeExp.agg(my_mean) # 这里传入的是: 自定义函数对象, 不加引号.
data.groupby('continent').agg({'lifeExp': my_mean})
运行结果:
# 写法7: 分组后, 可以针对于 多列数据, 进行不同的聚合计算.
# 需求: 根据年份分组, 计算: lifeExp(预期寿命)的平均值, pop(平均人口)的 最大值, gdpPercap(平均GDP) 的 中位数.
data.groupby('year').agg({'lifeExp': 'mean', 'pop': 'max', 'gdpPercap': 'median'})
运行结果:
transform()方法在Pandas库中是一个强大的工具,尤其在分组计算时。当对数据进行分组操作后,transform()方法允许对每个分组应用一个函数,并返回与原始DataFrame形状相同的结果。这对于在分组后进行标准化、填充缺失值、计算分组统计量等操作非常有用。
当与groupby()结合使用时,transform()的语法基本保持不变:
grouped.transform(func, *args, **kwargs)
其中,grouped是一个通过groupby()方法得到的分组对象,func是你想要应用于每个分组的函数。
# 创建一个简单的DataFrame
df = pd.DataFrame({
'category': ['A', 'A', 'B', 'B', 'C', 'C'],
'sales': [100, 150, 75, 125, 50, 70],
'profit': [20, 30, 15, 25, 10, 14]
})
print('原表:')
print(df)
# 使用groupby和transform计算每组的销售额均值,并将结果广播回原始形状
df['sales_mean_per_category'] = df.groupby('category')['sales'].transform('mean')
print('转换之后的表:')
df
运行结果:
输出将是一个新的DataFrame,其中包含一个额外的列sales_mean_per_category,该列包含了每个产品类别的销售额均值,并且这个均值被填充到了该类别下的每一行中。
通过transform()方法,你可以轻松地在分组后对数据进行各种转换和操作,而无需改变原始数据的形状或结构。这使得它在数据清洗、预处理和特征工程等任务中非常有用。
首先我们创建一个Dataframe
# 示例DataFrame
import pandas as pd
df = pd.DataFrame({
'A': ['foo', 'foo', 'foo', 'bar', 'bar'],
'B': ['one', 'one', 'two', 'two', 'one'],
'C': ['small', 'large', 'large', 'small', 'small'],
'D': [1, 2, 2, 3, 3],
'E': [2, 4, 5, 5, 6]
})
df
运行结果:
常见的是使用query或布尔索引来直接过滤DataFrame。
# 选择列'D'的值大于2的行
filtered_df = df.query('D > 2')
filtered_df
运行结果:
# 选择列'D'的值大于2的行
filtered_df = df[df['D'] > 2]
filtered_df
运行结果:
分组后过滤组可用filter函数传入一个lambda函数或自定义函数,进行组的过滤
# 查看按A分组的组内Dde平均值
c = df.groupby('A')[['D']].mean()
print(c)
# 过滤出按A分组的组内的平均值大于2的
df.groupby('A')['D'].filter(lambda x:x.mean()>2 )
运行结果:
# 定义一个自定义函数,功能是guol出平均值大于2的
def my_func(col):
if col.mean()>2:
return True
return False
df.groupby('A')['D'].filter(my_func)
运行结果:
注意:
无论是apply函数还是transform函数还是filter函数,在传入一个自定函数的时候,只需要传入函数名,而非函数名+()
pivot_table函数是用于创建数据透视表(pivot table)的强大工具。数据透视表是一种可以对数据进行汇总、分析、探索和呈现的有效方式,它允许用户根据一个或多个键对数据进行重排,并对结果进行聚合运算。功能的同于excel的数据透视表相同。
pandas.pivot_table(data, values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, dropna=True, margins_name='All')
import pandas as pd
data = {
'year': [2020, 2020, 2021, 2021, 2021],
'product': ['A', 'B', 'A', 'B', 'C'],
'region': ['North', 'North', 'South', 'South', 'East'],
'sales': [100, 200, 150, 300, 50]
}
df = pd.DataFrame(data)
df
数据样式:
# 每个商品每年的总的销售数量
pivot_table = df.pivot_table(values='sales', index='year', columns='product', aggfunc='sum')
pivot_table
运行结果:
# 每个商品每年在每个地区的销售总量
pivot_table = df.pivot_table(values='sales', index=['year', 'region'], columns='product', aggfunc='sum')
pivot_table
运行结果:
在这个例子中,我们添加了region作为第二层索引。
# 求每个产品,每年的销售总量和平均销售量
pivot_table = df.pivot_table(values='sales', index='year', columns='product', aggfunc=['sum', 'mean'])
pivot_table
运行结果:
这里我们使用了两个聚合函数:sum和mean。这将产生一个多层级的列标签。
# 将缺失值填充为0
pivot_table = df.pivot_table(values='sales', index='year', columns='product', aggfunc='sum', fill_value=0)
pivot_table
运行结果:
如果某些组合在数据中没有出现,则可以使用fill_value参数为这些缺失的组合填充一个默认值。
pivot_table = df.pivot_table(values='sales', index='year', columns='product', aggfunc='sum', margins=True)
pivot_table
运行结果:
通过调整index、columns和aggfunc等参数,你可以创建出各种复杂的数据透视表,以满足不同的数据分析需求。
Pandas的时间转换
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。