NumPy+Pandas数据分析基础完全指南

0 阅读9分钟

Python数据分析必备:numpy与pandas核心用法全总结(详细代码注释)

两个最重要的数据分析包:numpypandas,本文从零开始,每行代码都有注释,帮你彻底搞懂这两个库。


一、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 的核心用法总结,覆盖了数据分析中最常用的操作。建议收藏备用,每次写数据处理代码时都可以对照查阅。