【笔记整理|2024年上半年】Python数据分析与可视化技术指南
本文汇总了在科研数据分析中使用Python的实用技巧,涵盖数据处理、可视化、性能分析等核心技术。
NumPy和SciPy数据处理
数组操作和统计分析
寻找数组中的局部极值
使用scipy.signal.argrelextrema函数寻找一维数组中的相对极值(最大值和最小值):
import numpy as np
from scipy.signal import argrelextrema
from scipy.stats import gaussian_kde
# 示例:寻找密度函数的局部最小值
data = np.array([...]) # 你的数据
density = gaussian_kde(data)
x = np.linspace(data.min(), data.max(), 1000)
y = density(x)
# 寻找局部最小值
minima_indices = argrelextrema(y, np.less)
minima = x[minima_indices]
注意:argrelextrema函数寻找y是局部最小值的索引(即小于其邻居的点)。
数组处理常见问题
# 处理数组转换失败的问题
# "cannot process into arrays" 错误通常是由于数据类型不一致
try:
arr1 = np.array(str1.split())
result = np.array([float(x) for x in arr1])
except ValueError as e:
print(f"Array conversion failed: {e}")
数据可视化
Matplotlib配置和使用
基础导入和配置
import matplotlib.pyplot as plt
import matplotlib
# 获取matplotlib缓存目录
cache_dir = matplotlib.get_cachedir()
print(f"Matplotlib cache directory: {cache_dir}")
字体和缓存问题解决
import os
import matplotlib
# 清理matplotlib字体缓存
font_directory = os.path.join(matplotlib.get_data_path(), 'fonts', 'ttf')
# 如果遇到字体问题,删除缓存重新生成
# rm -r /home/username/.cache/matplotlib
Seaborn可视化技巧
Violin Plot使用和问题解决
import seaborn as sns
import matplotlib.pyplot as plt
# 创建violin plot
sns.violinplot(data=data)
# 常见问题:分布显示为负值(但数据全为正)
# 解决方案:使用内核密度估计的截断参数
sns.violinplot(data=data, cut=0) # cut=0避免扩展到数据范围之外
问题说明:使用sns.violinplot时发现某些分布低于0,但数据全为正值。这是因为核密度估计默认会在数据范围外进行插值。
Violin Plot进阶用法
Violin Plot数据分析指南:https://www.geeksforgeeks.org/violin-plot-for-data-analysis/
分组柱状图制作
多种方法实现分组柱状图
当数据格式为矩阵时,创建分组柱状图的5种方法:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# 方法1:使用matplotlib
def method1_matplotlib(data_matrix):
x = np.arange(len(data_matrix))
width = 0.35
fig, ax = plt.subplots()
for i in range(data_matrix.shape[1]):
ax.bar(x + i*width, data_matrix[:, i], width, label=f'Group {i+1}')
ax.legend()
# 方法2:使用pandas
def method2_pandas(data_matrix):
df = pd.DataFrame(data_matrix)
df.plot(kind='bar', ax=plt.gca())
# 方法3:使用seaborn
def method3_seaborn(data_matrix):
df = pd.DataFrame(data_matrix)
df_melted = df.melt()
sns.barplot(data=df_melted, x='variable', y='value')
# 其他方法可参考plotnine等工具
Pandas数据操作
基础数据处理
import pandas as pd
# 基本数据导入和处理
df = pd.read_csv('data.csv')
数据结构操作
字典排序
# 按键对字典进行排序
mydict = {'c': 3, 'a': 1, 'b': 2}
sorted_mydict = dict(sorted(mydict.items(), key=lambda item: item[0]))
Python字典排序指南:https://www.golinuxcloud.com/python-sort-dictionary-by-key/
性能分析与优化
代码性能分析
cProfile性能分析
在Python中,可以使用cProfile模块来分析每个函数的执行时间:
import cProfile
cProfile.run('your_function()')
不同运行环境性能对比
实际测试发现:
- PyCharm profile:71秒
- 简单debug模式:56秒
- 命令行直接运行:31秒
性能分析显示主要耗时操作:
- fit操作:约8秒
- concat操作:6秒
- process_dict:11.6秒
算法复杂度理解
Python排序算法
Python内置的sorted()函数使用双轴快排算法(timsort),时间复杂度:
- 最坏情况:O(n * log n)
- 平均情况:O(n * log n)
W3Schools Python sorted()函数:https://www.w3schools.com/python/ref_func_sorted.asp
哈希表查找效率
集合和字典在Python中都通过哈希表实现,元素查找时间复杂度通常为O(1),这使得元素位置可以快速定位。
高阶函数与函数式编程
函数套用(高阶函数)
在Python中,函数可以套用函数,这是一种常见的编程模式,也被称为高阶函数。这意味着一个函数可以接受另一个函数作为参数,或者返回一个函数作为结果。
动态属性设置
# 使用setattr动态设置对象属性
setattr(obj, 'attribute_name', value)
# __getattr__方法在访问不存在的属性时被调用
def __getattr__(self, name):
# 处理不存在的属性访问
pass
图论和网络分析
节点连接分析
处理图中节点组之间的连接问题:
# 问题:找到连接两个节点组的节点对
# 可能每个节点组对有一个节点对连接
# 解决思路:构建二分图可能有助于快速找到这些连接
def find_connecting_pairs(graph, group1, group2):
"""
找到连接两个节点组的节点对
考虑使用二分图表示来优化搜索
"""
connecting_pairs = []
for node1 in group1:
for node2 in group2:
if graph.has_edge(node1, node2):
connecting_pairs.append((node1, node2))
return connecting_pairs
列表元素计数
# 统计列表中元素出现次数的多种方法
from collections import Counter
# 方法1:使用Counter
my_list = [1, 2, 2, 3, 3, 3]
counts = Counter(my_list)
Python列表元素计数方法:https://datagy.io/python-count-occurrences-in-list/
组合与迭代
列表组合生成
import itertools
# 获取两个列表的所有唯一组合
combinations = list(itertools.product(list1, list2))
Python组合生成教程:https://www.geeksforgeeks.org/python-program-to-get-all-unique-combinations-of-two-lists/
迭代中修改集合
# 错误示例:迭代过程中修改集合大小
RuntimeError: Set changed size during iteration
避免在迭代过程中修改正在迭代的集合。
科研数据处理最佳实践
数据验证
def validate_data(data):
"""验证科研数据的基本检查"""
# 检查数据范围合理性
if np.any(data < 0) and data_should_be_positive:
print("Warning: Found negative values in positive-only data")
# 检查缺失值
if np.any(np.isnan(data)):
print("Warning: Found NaN values")
# 检查异常值
q1, q3 = np.percentile(data, [25, 75])
iqr = q3 - q1
outliers = (data < q1 - 1.5*iqr) | (data > q3 + 1.5*iqr)
if np.any(outliers):
print(f"Warning: Found {np.sum(outliers)} potential outliers")
可重现性保证
# 设置随机种子确保结果可重现
np.random.seed(42)
# 保存分析环境信息
def save_environment_info():
import sys
import numpy
import matplotlib
import pandas
env_info = {
'python_version': sys.version,
'numpy_version': numpy.__version__,
'matplotlib_version': matplotlib.__version__,
'pandas_version': pandas.__version__
}
return env_info
大数据处理
# 处理大型数组时的内存优化
def process_large_array(data, chunk_size=1000):
"""分块处理大型数组"""
results = []
for i in range(0, len(data), chunk_size):
chunk = data[i:i+chunk_size]
processed_chunk = process_chunk(chunk)
results.append(processed_chunk)
return np.concatenate(results)
向量化计算
# 优先使用NumPy向量化操作而非Python循环
# 低效方式
def slow_calculation(data):
results = []
for x in data:
results.append(x**2 + 2*x + 1)
return results
# 高效方式
def fast_calculation(data):
return data**2 + 2*data + 1
第三方库和工具
Plotnine使用
# plotnine相关问题和解决方案
Plotnine GitHub问题:https://github.com/has2k1/plotnine/issues/79
plotnine是Python中ggplot2的实现,适合熟悉R语法的用户。
调试和故障排除
常见错误模式
- 数组转换失败:通常由数据类型不一致造成
- 可视化异常值:密度估计超出数据范围
- 内存不足:大数据集处理时的常见问题
- 迭代修改错误:在迭代过程中修改集合
调试建议
- 使用
print()语句检查中间结果 - 利用Jupyter notebook的交互式特性
- 保存关键步骤的中间数据
- 记录完整的软件环境信息
本文基于2023年9月至2024年上半年的技术实践整理,涵盖Python数据分析和可视化的核心技术要点