Python数据分析必备:numpy与pandas核心用法全总结(详细代码注释)
两个最重要的数据分析包:numpy 和 pandas,本文从零开始,每行代码都有注释,帮你彻底搞懂这两个库。
一、numpy 数组创建(详细代码注释)
# =============================================
# numpy 数组创建大全 | 公主号:船长Talk
# =============================================
import numpy as np
# 01 最基础的构造方法:从列表创建一维数组
arr1 = np.array([1, 2, 3, 4, 5])
print(arr1) # out: array([1, 2, 3, 4, 5])
# 02 创建二维数组(矩阵)
data = [[1, 2, 3, 4], [5, 6, 7, 8]]
arr2 = np.array(data)
print(arr2.shape) # 输出形状 out(2,4),表示2行4列
# 03 用元组创建array
data3 = (1, 2, 3, 4, 5) # tuple元组
arr3 = np.array(data3)
print(arr3) # out: array([1,2,3,4,5])
# 04 全零数组:np.zeros
arr6 = np.zeros((3, 2)) # 创建一个3行2列的全0数组
arr6_1 = np.zeros_like(arr6) # 创建形状和arr6相同的全0数组(常用于初始化)
# 全1数组:np.ones
arr7 = np.ones((3, 2)) # 3行2列全1,注意不是全0
# 05 正态分布数组:np.empty (未初始化,值随机)
arr9 = np.empty(20) # 创建长度为20的空数组,值不确定
# 06 有序数组:range的步长不能为浮点型,arange()可以浮点
arr10 = np.array(range(10)) # Python的range,整数
arr10_1 = np.arange(1, 10, 0.1) # numpy的arange,支持浮点步长(属于numpy范畴)
# 08 随机数组
np.random.rand(10) # 0~1之间均匀分布随机数
arr12 = np.random.randn(10000) # 标准正态分布随机数组(均值0,标准差1)
print("平均值:", arr12.mean()) # 计算平均数,理论上接近0
print("标准差:", arr12.std()) # 计算标准差,理论上接近1
# 09 创建带形状的随机整数数组
np.random.seed(42) # 指定随机种子42,保证结果可复现
arr13 = np.random.randint(1, 100, 10).reshape(5, 2) # 生成10个1-100的随机整数,reshape为5行2列
print(arr13)
# 10 线性等分数组:linspace(比arange更精准)
arr14 = np.linspace(11, 21, 100, endpoint=False) # 从11到21,等分100份,不包括结尾
# 11 单位矩阵(主对角线为1,其他为0)
arr15 = np.eye(5) # 5行5列的单位矩阵,对角线为1
print(arr15)
二、numpy 核心方法(索引、运算、函数)
# =============================================
# numpy 核心操作 | 公主号:船长Talk
# =============================================
import numpy as np
# ---- 常用属性 ----
data1 = [[6, 7.5, 8, 0, 1], [1, 2, 3, 4, 5]]
arr1 = np.array(data1)
print(arr1.ndim) # 数组维度个数(本例为2,表示二维)
print(arr1.shape) # 数组形状,几行几列(2行5列)
print(arr1.size) # 元素总数,m行n列的数组,元素总数为m*n
print(arr1.dtype) # 元素数据类型(本例float64)
print(arr1.itemsize) # 每个元素占用的字节数
# ---- 布尔索引(高级特性)----
names = np.array(['1', '2', '3', '4', '5', '6', '7'])
col = np.array(range(4))
data = np.random.randn(7, 4) # 7行4列随机数据
# 原理:names=='2'会生成[False,True,False,...]这样的bool数组,用来筛选行
print(data[names == '2'])
# 同时指定行和列的条件筛选
data[names == '2', col == 1] # 第'2'行,第1列
data[names == '2', (col == 1) | (col == 2)] # 第'2'行,第1或第2列(逻辑或要加括号)
# ---- 花式索引 ----
arr = np.arange(16).reshape(4, 4)
arr[[4, 1]] # 先取第4行,再取第1行(打乱顺序取行)
arr[[-1, -3, 3]] # 支持负数索引,-1代表最后一行
# ---- 转置 ----
arr.T # 行列互换(属性),[0,0]不变,左下和右上互换
arr.transpose # 方法,结果和arr.T一样
# ---- 矢量计算(numpy核心优势)----
arr3 = np.array([1, 2, 3, 4, 5])
arr3 * 2 # arr3所有元素乘以2,这就是矢量计算,比for循环快10-100倍
# ---- 常用数学函数 ----
arr = np.array([1, np.e, np.e**2, 0])
print("数组最大值:%s" % (np.max(arr)))
print("数组最小值:%s" % (np.min(arr)))
print("以e为基数求e的数组次方%s" % np.exp(arr)) # e的x次方
print("自然对数%s" % np.log(arr)) # ln(x),注意0的对数为-inf
print("开方%s" % np.sqrt(arr))
print("平均值%s" % np.mean(arr))
print("标准差%s" % np.std(arr))
print("最小值的索引%s" % np.argmin(arr)) # 返回最小值在数组中的位置
print("最大值的索引%s" % np.argmax(arr)) # 返回最大值在数组中的位置
print("判断是否为无穷大:%s" % np.isinf(arr)) # 检查是否有inf值
# ---- where 函数(条件选择,非常实用)----
xarr_1 = np.array([1, 2, 3, 4, 5, 6, 7, 8])
yarr_2 = np.array([1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8])
cond = ([True, False, True, True, True, False, False, False])
# 当cond为True时从xarr_1取值,否则从yarr_2取值
result = np.where(cond, xarr_1, yarr_2)
print(result)
# ---- 排序 ----
np.sort(arr) # 升序排列(返回新数组,不改变原数组)
np.sort(arr, axis=1) # 按列方向排序
# ---- 堆叠 ----
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
np.hstack((a, b)) # 横向堆叠(往右加列),结果是2行4列
np.vstack((a, b)) # 纵向堆叠(往下加行),结果是4行2列
三、pandas Series 基础用法
# =============================================
# pandas Series 创建与基本操作 | 公主号:船长Talk
# =============================================
import numpy as np
import pandas as pd
# Series:带标签的一维数组(比numpy数组多了索引labels)
ser = pd.Series([10, 20, 30, 40]) # index默认0,1,2,3
ser2 = pd.Series([10, 20, 30], index=['a', 'b', 'c']) # 自定义索引
# 常用方法
print(ser.isnull()) # 检查哪些值是NaN(缺失值)
print(pd.isnull(ser)) # 同上,函数写法
print(ser.values) # 获取底层numpy数组
print(ser.index) # 获取索引对象
四、pandas DataFrame 完整教程(详细代码注释)
# =============================================
# pandas DataFrame 全操作指南 | 公主号:船长Talk
# =============================================
import numpy as np
import pandas as pd
# 01 从字典创建DataFrame(最常见方式)
data = {
"city": ['北京', '上海', '广州', '深圳'],
"year": [2020, 2021, 2022, 2023],
'population': [2154, 2487, 1867, 1756] # 单位:万人
}
frame = pd.DataFrame(data)
# 字典的key自动变成列名,列表的每个元素是对应行的值
# 02 查看列(返回Series对象)
frame['year'] # 方法1:用列名取列(推荐,通用)
frame.year # 方法2:用属性取列(注意:列名不能有空格)
# 03 花式索引:同时取多列
frame[['population', 'city', 'year']] # 传入列名列表,返回新DataFrame
# 04 指定列顺序,多出的列会填充NaN
frame2 = pd.DataFrame(data, columns=['population', 'city', 'year', 'GDP'])
# 新增的GDP列,值全部为NaN(缺失值)
# 05 loc 索引(按标签)
frame2.loc[['a', 'b'], ['year', 'population']] # 前面是行标签,后面是列标签
# 06 iloc 索引(按整数位置,更常用)
frame2.iloc[0:2, 0:3] # 取前2行,前3列
frame2.iloc[0:2, [0, 3]] # 取前2行,第0列和第3列
# ---- 数据增删改 ----
# 07 赋值(修改一列)
frame2['GDP'] = [2.4, 3.9, 2.7, 2.1] # 行数要匹配
# 08 删除列(两种方式)
del frame2['GDP'] # 方式1:直接删除,原地修改
frame2.drop(['year'], axis=1, inplace=False) # 方式2:drop方法
# axis=1代表列方向,inplace=False表示不修改原数据(返回新DataFrame)
# inplace=True才会原地修改!
# 09 添加新列
frame2['location'] = ['华北', '华东', '华南', '华南'] # 行数要匹配
# 10 apply 方法(对每个元素应用函数,非常强大)
frame = pd.DataFrame(np.random.randn(4, 3), columns=list('bde'), index=list('1234'))
# 普通函数写法
def add_one(x):
return x + 1
frame['b'].apply(add_one) # 对b列每个元素+1
frame['b'].apply(lambda x: x + 1) # lambda写法,更简洁
# ---- 排序操作 ----
# 11 按索引排序(行的名字)
frame.sort_index() # 默认按行索引升序排列
frame.sort_index(axis=1, ascending=False) # 按列名降序排列
# 12 按值排序(更常用)
frame.sort_values(by='b', ascending=False) # 按b列的值降序排列
# ascending=False 是降序(从大到小);True是升序(默认)
# ---- 去重操作 ----
# 13 查看唯一值
frame['b'].unique() # 返回该列的去重后唯一值数组
# 14 删除重复行
frame.drop_duplicates(['列1', '列2'], keep='last')
# keep='first'保留第一次出现;keep='last'保留最后一次出现
# 15 查看哪些行是重复的
frame.duplicated() # 返回bool Series,True代表是重复行
# 16 填充缺失值(NaN处理,实战必用)
frame['b'].fillna(frame['b'].mean()) # 用均值填充
frame['b'].fillna(frame['b'].mode()[0]) # 用众数填充
frame['b'].fillna(frame['b'].std()) # 用标准差填充(较少用)
frame.fillna(method='ffill', limit=2) # 前向填充(用前一个值填),limit限制最多填几个
frame.fillna(method='bfill') # 后向填充(用后一个值填)
# 17 map映射(字段值替换,很常用)
# 把数字映射为文字
mapping = {1: '优秀', 2: '良好', 3: '及格', 4: '不及格'}
frame['b'].map(mapping) # 对b列每个值按字典映射
五、lambda + map + filter + reduce(函数式编程基础)
# =============================================
# Python函数式编程三剑客 | 公主号:船长Talk
# =============================================
from functools import reduce
# --- map:对每个元素执行同一操作 ---
list1 = list(map(lambda x: x + 2, [1, 2, 3, 4, 5, 6, 7, 8, 10, 12]))
# lambda x: x+2 表示:对后面列表中的每个元素x,执行x+2操作
print(list1) # [3, 4, 5, 6, 7, 8, 9, 10, 12, 14]
# --- filter:筛选满足条件的元素 ---
even_list = list(filter(lambda x: x % 2 == 0, [1, 2, 3, 4, 5, 6, 7, 8]))
# 筛选x%2==0的数(偶数)
print(even_list) # [2, 4, 6, 8]
# --- reduce:累计运算 ---
# 计算[1,2,3,4,5,6,7,8]的累加和
a_2 = reduce(lambda x, y: x + y, [1, 2, 3, 4, 5, 6, 7, 8])
# lambda x,y: x+y 就是把相邻两个数相加,依次累计
print(a_2) # 36
六、pandas 实用技巧(数据清洗常用)
# =============================================
# pandas 数据清洗实用技巧 | 公主号:船长Talk
# =============================================
import pandas as pd
import numpy as np
# --- 关闭科学计数法显示(处理大数字时必用)---
pd.set_option('float_format', lambda x: '%.0f' % x)
# 让pandas不用科学计数法(如1.23e+08)展示,而是直接显示整数
# --- 模糊匹配(字符串包含匹配)---
data = pd.DataFrame({'name': ['Beijing', 'Shanghai', 'Guangzhou', 'Shenzhen'],
'score': [90, 85, 78, 92]})
# 找出name中包含'ang'的行
result = data[data['name'].str.contains('ang')]
print(result)
# str.contains 支持正则表达式
# 匹配以S开头的城市:
data[data['name'].str.contains('^S')]
# --- groupby 聚合分析(数据分析核心操作)---
df = pd.DataFrame({
'city': ['北京', '北京', '上海', '上海', '广州'],
'sales': [100, 200, 150, 120, 80],
'year': [2022, 2023, 2022, 2023, 2022]
})
# 按城市分组,计算每个城市的销售额总和
city_sales = df.groupby('city')['sales'].sum()
print(city_sales)
# 按城市分组,同时计算均值、求和、最大值
df.groupby('city')['sales'].agg(['mean', 'sum', 'max'])
# 多字段groupby
df.groupby(['city', 'year'])['sales'].sum()
# --- merge 数据关联(类似SQL的JOIN)---
df1 = pd.DataFrame({'id': [1, 2, 3], 'name': ['Alice', 'Bob', 'Charlie']})
df2 = pd.DataFrame({'id': [1, 2, 4], 'score': [90, 85, 78]})
# 内联接(只保留两表都有的id)
pd.merge(df1, df2, on='id', how='inner')
# 左连接(保留df1所有行,df2没有的填NaN)
pd.merge(df1, df2, on='id', how='left')
以上是 numpy 和 pandas 的核心用法总结,覆盖了数据分析中最常用的操作。建议收藏备用,每次写数据处理代码时都可以对照查阅。