pandas 和 numpy相关函数详解
一、关键名词解释
- np 代表numpy库
- pd 代表pandas库
- df 代表dataframe对象,df的每一列都是sd类型的数据
- sd 代表Series对象,numpy中的一维数组与sd可以互相转换,sd=pd.Series(np.array([1, 2, 3, 4]))
- myvar = pd.Series(a) 是Series类型
- b=np.array(myvar) 是一维数组类型
- sd
- len(df) 返回一个df的行数,len(df.index) :行数、len(df.columns):列数
二、函数详解
1、np.where(condition[, x, y])
- condition: 一个布尔数组(array_like)。这是必需的参数。它定义了选择的条件。
- x, y: 可选参数(array_like)。它们必须与 condition具有可广播到相同形状的形状(或者可以是标量)。
- 当提供了 x和 y时,函数执行三元操作:where(condition, x, y)返回一个数组,其中 condition为 True的位置取自 x,为 False的位置取自 y。
- 当 只提供 condition 时,函数返回一个元组(通常是长度为 condition.ndim的元组),其中包含满足条件(condition == True)的元素的 索引数组
用法一:仅提供 condition- 获取满足条件的索引
- 功能 :找出输入数组中所有满足条件 condition == True的元素的索引。
- 返回值 :一个元组(tuple),包含 n个数组(n是 condition的维度)。每个数组对应一个维度,包含了该维度上满足条件的索引。
- 对于 一维数组:返回一个包含一个数组的元组,该数组是满足条件的元素的索引。
- 对于 二维数组: 返回一个包含两个数组的元组。第一个数组是满足条件的元素的行索引,第二个数组是满足条件的元素的列索引。这些索引数组可以一起使用来获取满足条件的元素(例如 arr[row_indices, col_indices])。
import numpy as np# 一维数组示例
arr = np.array([1, 5, 2, 8, 3])
indices = np.where(arr > 3)
print(indices) # 输出: (array([1, 3]),) 一个元组,里面包含一个索引数组 [1, 3]
print(arr[indices]) # 输出: [5 8] 使用这些索引获取元素# 二维数组示例
arr2d = np.array([[1, 2, 10],[4, 5, 6],[7, 8, 9]])
indices2d = np.where(arr2d > 5)
print(indices2d)
# 输出: (array([0, 1, 1, 2, 2, 2]), # 行索引
# array([2, 1, 2, 0, 1, 2])) # 列索引# 使用行索引和列索引获取满足条件的元素
print(arr2d[indices2d]) # 输出: [10 6 8 7 8 9]# 找出值等于特定元素的索引
indices_eq = np.where(arr2d == 8)
print(indices_eq) # 输出: (array([2]), array([1]))
print(arr2d[indices_eq]) # 输出: [8]
用法二:提供 condition, x, y- 三元选择(类似 x if condition else y)
- 功能: 根据 condition的真假,从 x或 y中选择元素来构造一个新的数组。这相当于对数组中的每个元素执行 x[i] if condition[i] else y[i]。
- 返回值: 一个与 condition、x、y广播后形状相同的数组。
- 广播规则: condition、x、y必须可以广播到相同的形状。标量可以广播到任何形状。
import numpy as np# 基本用法:用0替换小于等于5的元素,保持原值
arr = np.array([1, 5, 2, 8, 3])
result = np.where(arr > 5, arr, 0) # 条件为True选arr对应元素,False选0
print(result) # 输出: [0 0 0 8 0]# 在两个数组间选择
x = np.array([10, 10, 10, 10, 10])
y = np.array([-1, -1, -1, -1, -1])
result2 = np.where(arr > 3, x, y) # >3选10,否则选-1
print(result2) # 输出: [-1 10 -1 10 -1]# 二维数组示例
arr2d = np.array([[1, 2, 10],[4, 5, 6],[7, 8, 9]])
# 大于5的位置保持原值,否则设为-100
result2d = np.where(arr2d > 5, arr2d, -100)
print(result2d)
# 输出:
# [[-100 -100 10]
# [-100 -100 6]
# [ 7 8 9]]# 使用标量广播
# 偶数设为0,奇数设为1
arr_even_odd = np.array([2, 7, 4, 9, 6])
result_eo = np.where(arr_even_odd % 2 == 0, 0, 1)
print(result_eo) # 输出: [0 1 0 1 0]# 更复杂的条件:使用逻辑运算符 (&, |, ~)
# 值在3到7之间(包含)的设为True(1),否则设为False(0)
result_range = np.where((arr >= 3) & (arr <= 7), 1, 0)
print(result_range) # 输出: [0 1 0 0 1] (5和3在3-7之间)
2、sd.value_counts(normalize=False, sort=True, ascending=False, bins=None, dropna=True)
要用于计算一个 Series 中每个唯一值出现的次数(即频数统计)。它返回一个新的 Series,索引是原始 Series 中的唯一值,值是对应的频数,默认按频数降序排列。
| 参数 | 含义 |
|---|---|
| normalize: bool, 默认为 False | 如果为 False,返回的是每个值的频数(绝对计数),如果为 True,返回的是每个值的频率(相对比例,总和为 1)。 |
| sort: bool, 默认为 True | 如果为 True,结果 Series 会按照频数(或频率)进行排序。如果为 False,则按照值在原始数据中首次出现的顺序排序 |
| ascending: bool, 默认为 False | 当 sort=True时,此参数生效。如果为 False,结果按频数(或频率)降序排列(从大到小)。如果为 True,则按升序排列(从小到大) |
| dropna: bool, 默认为 True | 如果为 True,则在计数时不包括 NaN值。如果为 False,则会将 NaN也作为一个类别进行计数 |
import pandas as pd
data = pd.Series(['a', 'b', 'a', 'c', 'b', 'a'])
print(data.value_counts())
# a 3
# b 2
# c 1
# dtype: int64print(data.value_counts(normalize=True))
# a 0.500000
# b 0.333333
# c 0.166667
# dtype: float64
3、df.value_counts( subset=None, normalize=False, sort=True,ascending=False, dropna=True)
DataFrame具有value_counts方法,用于计算DataFrame中唯一行的频率,返回一个包含唯一行及其计数的Series。返回值是一个Series,其索引是DataFrame的唯一行(以MultiIndex形式),值是计数(或比例,如果normalize=True)。
| 参数 | 含义 |
|---|---|
| normalize: bool, 默认为 False | 如果为 False,返回的是每个值的频数(绝对计数),如果为 True,返回的是每个值的频率(相对比例,总和为 1)。 |
| sort: bool, 默认为 True | 如果为 True,结果 Series 会按照频数(或频率)进行排序。如果为 False,则按照值在原始数据中首次出现的顺序排序 |
| ascending: bool, 默认为 False | 当 sort=True时,此参数生效。如果为 False,结果按频数(或频率)降序排列(从大到小)。如果为 True,则按升序排列(从小到大) |
| dropna: bool, 默认为 True | 如果为 True,则在计数时不包括 NaN值。如果为 False,则会将 NaN也作为一个类别进行计数 |
| subset=None, | 标签或标签列表,可选。指定要考虑的列。默认使用所有列。 |
3、pd.cut(x, bins, right=True, labels=None, retbins=False, precision=3, include_lowest=False, duplicates=‘raise’)
将一组连续数值分割成指定的区间(bins),并返回每个值所属的区间标签(或区间对象)。,常用于数据分组、区间统计或创建分类变量。以下是详细解析:
| 参数 | 详解 |
|---|---|
| x | 要分箱的一维数组(如 Series、列表、ndarray)。示例:df[‘age’], [1, 2, 3, 4, 5] |
| bins | 定义区间边界的方式:整数:将数据分成 n个等宽区间(区间数量 = bins)。列表/数组:自定义边界(如 [0, 18, 35, 60]),生成 n-1个区间。IntervalIndex:直接指定区间对象。 |
| right | 区间是否右闭合(默认 True):True:区间为 (a, b](左开右闭)。False:区间为 [a, b)(左闭右开)。 |
返回值类型与输入值有关
| 输入类型 | labels参数 | 返回值类型 | 返回值内容 |
|---|---|---|---|
| Series | None(默认) | Series | dtype: category |
| Series | 自定义标签列表 | Series | dtype: category |
| Series | False | Series | dtype: int |
| 其他一维数组 | None(默认) | Categorical | Interval对象 |
| 其他一维数组 | 自定义标签列表 | Categorical | 自定义标签 |
| 其他一维数组 | False | ndarray | 整数编码 |
4、df.groupby详解
语法如下
DataFrame.groupby(by=None,axis=0,level=None,as_index=True,sort=True,group_keys=True,squeeze=<no_default>,observed=False,dropna=True
)
核心思想:拆分(Split)- 应用(Apply)- 合并(Combine)
- 拆分 (Split): 根据提供的键(by参数)将 DataFrame 或 Series 分割成多个组(GroupBy对象)。
- 应用 (Apply): 对每个分组独立地应用一个函数。这个函数可以是:
- 聚合 (Aggregation): 计算组的汇总统计量(如 sum(), mean(), count(), max(), min(), std(), var(), describe()等)。结果是每个组一个值。
- 转换 (Transformation): 对组内的每个元素进行操作,返回一个与组内原始数据形状相同的对象(如 transform())。常用于组内标准化、填充缺失值等。
- 过滤 (Filtration): 根据组的计算结果(如 sum()或 mean())决定是否丢弃整个组(如 filter())。返回的是满足条件的组的原始数据子集。
- 合并 (Combine): 将应用函数后的结果组合成一个新的 DataFrame 或 Series。
参数|详解
by|可以是列名(字符串)、列名的列表(用于多级分组),对于上述列中值一致的进行分组
axis:|分组轴,默认为0(按行分组)。1表示按列分组(较少使用)。
dropna:|默认为True。如果为True,则在分组前删除分组键中包含NA值的行/列;如果为False,则NA值将被视为一个分组。
该值返回一个<class ‘pandas.core.groupby.generic.DataFrameGroupBy’>类型(可以认为是以一个三维数组),这个对象本身并不包含数据,而是包含了分组的信息以及后续操作的方法(如聚合、转换、过滤等)。
data = {'City': ['Beijing', 'Shanghai', 'Guangzhou', 'Shenzhen', 'Beijing', 'Shanghai', 'Guangzhou'],'Product': ['A', 'B', 'A', 'C', 'B', 'A', 'B'],'Sales': [100, 150, 200, 120, 180, 90, 220],'Quantity': [10, 15, 20, 12, 18, 9, 22]
}
df= pd.DataFrame(data)grouped=df.groupby('City')
print(df)City Product Sales Quantity
0 Beijing A 100 10
1 Shanghai B 150 15
2 Guangzhou A 200 20
3 Shenzhen C 120 12
4 Beijing B 180 18
5 Shanghai A 90 9
6 Guangzhou B 220 22
对grouped进行聚合操作
print(grouped['Sales'])
<pandas.core.groupby.generic.SeriesGroupBy object at 0x0000022C0E5A68D0>
- grouped.sum() 对所有列都相加,返回的是一个DataFrame
print(grouped.sum())Product Sales Quantity
City
Beijing AB 280 28
Guangzhou AB 420 42
Shanghai BA 240 24
Shenzhen C 120 12
- grouped[].sum() 对指定列相加
print(grouped[['Sales','Quantity']].sum())Sales Quantity
City
Beijing 280 28
Guangzhou 420 42
Shanghai 240 24
Shenzhen 120 12
- 计算每组的平均值
grouped.mean() 类似于sum - 获取每组最大值
grouped.max() 类似于sum - 获取每组最小值
grouped.min() 类似于sum - 计算每组标准差
grouped.std() 类似于sum - 获取每组非NA值数量
grouped.count() 类似于sum
>>> print(grouped.count())Product Sales Quantity
City
Beijing 2 2 2
Guangzhou 2 2 2
Shanghai 2 2 2
Shenzhen 1 1 1
>>>
- 获取每组唯一值数量
grouped.nunique()类似于sum
>>> print(grouped.nunique())Product Sales Quantity
City
Beijing 2 2 2
Guangzhou 2 2 2
Shanghai 2 2 2
Shenzhen 1 1 1
>>>
- 多聚合操作
# 对同一列应用多个聚合函数
grouped['Sales'].agg(['sum', 'mean', 'max'])# 对不同列应用不同聚合函数
grouped.agg({'Sales': 'sum','Sales': ['mean','std'],'Quantity': 'max'
})
输出结果如下
>>> print(grouped['Sales'].agg(['sum', 'mean', 'max']))sum mean max
City
Beijing 280 140.0 180
Guangzhou 420 210.0 220
Shanghai 240 120.0 150
Shenzhen 120 120.0 120
>>> grouped.agg({
... 'Sales': 'sum',
... 'Sales': ['mean','std'],
... 'Quantity': 'max'
... })Sales Quantitymean std max
City
Beijing 140.0 56.568542 18
Guangzhou 210.0 14.142136 22
Shanghai 120.0 42.426407 15
Shenzhen 120.0 NaN 12
>>>
