|
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
引言
Python的pandas库是数据分析领域最核心的工具之一,它提供了强大的数据结构和数据分析工具。在pandas中,DataFrame(数据框)是最常用的数据结构,类似于电子表格或SQL表。在实际数据分析工作中,我们经常需要从数据框中选择、过滤和输出特定的行数据,这是数据分析的基础操作。掌握高效的数据框行操作技巧,可以显著提升数据分析的效率,使复杂的数据处理任务变得简单易行。本文将详细介绍从基础到高级的pandas数据框行操作技巧,帮助读者全面掌握这一必备技能。
基础行选择方法
使用loc和iloc选择行
在pandas中,loc和iloc是最基本也是最常用的行选择方法。loc基于标签索引,而iloc基于整数位置索引。
- import pandas as pd
- import numpy as np
- # 创建一个示例数据框
- data = {
- 'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eva'],
- 'Age': [25, 30, 35, 40, 45],
- 'City': ['New York', 'Los Angeles', 'Chicago', 'Houston', 'Phoenix'],
- 'Salary': [50000, 60000, 70000, 80000, 90000]
- }
- df = pd.DataFrame(data)
- # 使用loc选择行(基于标签)
- # 选择索引为0的行
- row_0 = df.loc[0]
- print("索引为0的行:")
- print(row_0)
- # 选择索引为0,2,4的行
- rows_024 = df.loc[[0, 2, 4]]
- print("\n索引为0,2,4的行:")
- print(rows_024)
- # 使用iloc选择行(基于整数位置)
- # 选择第一行(索引为0)
- first_row = df.iloc[0]
- print("\n第一行:")
- print(first_row)
- # 选择前3行
- first_3_rows = df.iloc[0:3]
- print("\n前3行:")
- print(first_3_rows)
- # 选择第1,3,5行
- rows_135 = df.iloc[[0, 2, 4]]
- print("\n第1,3,5行:")
- print(rows_135)
复制代码
使用head和tail方法
head和tail方法分别用于选择数据框的前N行和后N行,非常适合快速查看数据的开始和结束部分。
- # 选择前2行
- first_2 = df.head(2)
- print("前2行:")
- print(first_2)
- # 选择后3行
- last_3 = df.tail(3)
- print("\n后3行:")
- print(last_3)
复制代码
使用sample方法随机选择行
sample方法用于从数据框中随机选择行,这在需要创建随机样本或进行随机抽样时非常有用。
- # 随机选择2行
- random_2 = df.sample(n=2)
- print("随机选择2行:")
- print(random_2)
- # 随机选择50%的行
- random_50_percent = df.sample(frac=0.5)
- print("\n随机选择50%的行:")
- print(random_50_percent)
- # 随机选择3行,并设置随机种子以确保结果可重现
- random_3_seed = df.sample(n=3, random_state=42)
- print("\n随机选择3行(设置随机种子):")
- print(random_3_seed)
复制代码
条件过滤行数据
单条件过滤
使用布尔条件过滤数据框中的行是最常见的数据选择方式之一。
- # 选择年龄大于30的行
- age_gt_30 = df[df['Age'] > 30]
- print("年龄大于30的行:")
- print(age_gt_30)
- # 选择城市为'New York'的行
- city_ny = df[df['City'] == 'New York']
- print("\n城市为'New York'的行:")
- print(city_ny)
- # 选择工资不等于60000的行
- salary_ne_60000 = df[df['Salary'] != 60000]
- print("\n工资不等于60000的行:")
- print(salary_ne_60000)
复制代码
多条件过滤
使用逻辑运算符(&、|、~)组合多个条件,可以创建更复杂的过滤条件。
- # 选择年龄大于30且工资大于70000的行
- age_gt_30_salary_gt_70000 = df[(df['Age'] > 30) & (df['Salary'] > 70000)]
- print("年龄大于30且工资大于70000的行:")
- print(age_gt_30_salary_gt_70000)
- # 选择城市为'New York'或'Chicago'的行
- city_ny_or_chicago = df[(df['City'] == 'New York') | (df['City'] == 'Chicago')]
- print("\n城市为'New York'或'Chicago'的行:")
- print(city_ny_or_chicago)
- # 选择年龄不大于35的行
- age_le_35 = df[~(df['Age'] > 35)]
- print("\n年龄不大于35的行:")
- print(age_le_35)
复制代码
使用query方法进行过滤
query方法提供了一种使用字符串表达式过滤数据的便捷方式,特别适合复杂的过滤条件。
- # 使用query方法选择年龄大于30的行
- age_gt_30_query = df.query('Age > 30')
- print("使用query方法选择年龄大于30的行:")
- print(age_gt_30_query)
- # 使用query方法选择年龄大于30且工资大于70000的行
- age_gt_30_salary_gt_70000_query = df.query('Age > 30 and Salary > 70000')
- print("\n使用query方法选择年龄大于30且工资大于70000的行:")
- print(age_gt_30_salary_gt_70000_query)
- # 使用query方法选择城市为'New York'或'Chicago'的行
- city_ny_or_chicago_query = df.query('City == "New York" or City == "Chicago"')
- print("\n使用query方法选择城市为'New York'或'Chicago'的行:")
- print(city_ny_or_chicago_query)
- # 使用query方法结合外部变量
- min_age = 30
- age_gt_min = df.query('Age > @min_age')
- print("\n使用query方法结合外部变量选择年龄大于min_age的行:")
- print(age_gt_min)
复制代码
高级行过滤技巧
使用isin方法
isin方法用于选择列值在给定列表中的行,非常适合处理多值选择的情况。
- # 选择城市在'New York'、'Chicago'或'Phoenix'的行
- cities = ['New York', 'Chicago', 'Phoenix']
- selected_cities = df[df['City'].isin(cities)]
- print("城市在'New York'、'Chicago'或'Phoenix'的行:")
- print(selected_cities)
- # 选择年龄不在[25, 35]中的行
- age_not_in = df[~df['Age'].isin([25, 35])]
- print("\n年龄不在[25, 35]中的行:")
- print(age_not_in)
复制代码
使用str方法进行字符串过滤
str方法提供了多种字符串操作,可用于过滤包含特定字符串的行。
- # 创建一个包含更多文本数据的示例数据框
- data_text = {
- 'Product_ID': ['P001', 'P002', 'P003', 'P004', 'P005'],
- 'Product_Name': ['Laptop Pro', 'Smartphone X', 'Tablet Plus', 'Desktop Elite', 'Watch Smart'],
- 'Description': [
- 'High performance laptop for professionals',
- 'Latest smartphone with advanced features',
- 'Compact tablet with high resolution display',
- 'Powerful desktop for gaming and work',
- 'Smartwatch with health monitoring features'
- ],
- 'Price': [1200, 800, 400, 1500, 250]
- }
- df_text = pd.DataFrame(data_text)
- # 选择产品名称包含'Pro'的行
- name_contains_pro = df_text[df_text['Product_Name'].str.contains('Pro')]
- print("产品名称包含'Pro'的行:")
- print(name_contains_pro)
- # 选择描述以'High'开头的行
- desc_starts_high = df_text[df_text['Description'].str.startswith('High')]
- print("\n描述以'High'开头的行:")
- print(desc_starts_high)
- # 选择描述以'features'结尾的行
- desc_ends_features = df_text[df_text['Description'].str.endswith('features')]
- print("\n描述以'features'结尾的行:")
- print(desc_ends_features)
- # 选择产品名称包含'Pro'或'Smart'的行
- name_contains_pro_or_smart = df_text[df_text['Product_Name'].str.contains('Pro|Smart')]
- print("\n产品名称包含'Pro'或'Smart'的行:")
- print(name_contains_pro_or_smart)
复制代码
使用正则表达式过滤
正则表达式提供了更灵活的字符串匹配方式,可以实现复杂的模式匹配。
- # 选择产品ID以'P00'开头后跟一个数字的行
- id_pattern = df_text[df_text['Product_ID'].str.match(r'P00\d')]
- print("产品ID以'P00'开头后跟一个数字的行:")
- print(id_pattern)
- # 选择描述中包含'performance'或'resolution'的行
- desc_pattern = df_text[df_text['Description'].str.contains(r'performance|resolution')]
- print("\n描述中包含'performance'或'resolution'的行:")
- print(desc_pattern)
- # 选择产品名称中包含大写字母后跟小写字母的行
- name_pattern = df_text[df_text['Product_Name'].str.contains(r'[A-Z][a-z]+')]
- print("\n产品名称中包含大写字母后跟小写字母的行:")
- print(name_pattern)
复制代码
使用between方法
between方法用于选择列值在指定范围内的行,非常适合处理数值范围的选择。
- # 创建一个包含数值范围数据的示例数据框
- data_range = {
- 'Student_ID': ['S001', 'S002', 'S003', 'S004', 'S005', 'S006', 'S007', 'S008'],
- 'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eva', 'Frank', 'Grace', 'Henry'],
- 'Math_Score': [85, 92, 78, 65, 88, 72, 95, 81],
- 'English_Score': [90, 85, 82, 70, 88, 75, 92, 78],
- 'Science_Score': [88, 90, 75, 68, 85, 70, 93, 80]
- }
- df_scores = pd.DataFrame(data_range)
- # 选择数学成绩在80到90之间的学生
- math_between_80_90 = df_scores[df_scores['Math_Score'].between(80, 90)]
- print("数学成绩在80到90之间的学生:")
- print(math_between_80_90)
- # 选择英语成绩不低于85且不高于92的学生
- english_between_85_92 = df_scores[df_scores['English_Score'].between(85, 92)]
- print("\n英语成绩不低于85且不高于92的学生:")
- print(english_between_85_92)
- # 选择科学成绩在70到80之间的学生,不包括边界值
- science_between_70_80_exclusive = df_scores[df_scores['Science_Score'].between(70, 80, inclusive='neither')]
- print("\n科学成绩在70到80之间的学生(不包括边界值):")
- print(science_between_70_80_exclusive)
复制代码
处理缺失值的行选择
检测缺失值
使用isna或isnull方法检测缺失值,这是处理不完整数据的第一步。
- # 创建一个包含缺失值的示例数据框
- data_missing = {
- 'ID': [1, 2, 3, 4, 5],
- 'Name': ['Alice', 'Bob', np.nan, 'David', 'Eva'],
- 'Age': [25, np.nan, 35, 40, np.nan],
- 'Salary': [50000, 60000, np.nan, 80000, 90000],
- 'Department': ['HR', 'IT', 'Finance', np.nan, 'Marketing']
- }
- df_missing = pd.DataFrame(data_missing)
- # 检测数据框中的缺失值
- print("数据框中的缺失值:")
- print(df_missing.isna())
- # 选择Name列有缺失值的行
- name_na = df_missing[df_missing['Name'].isna()]
- print("\nName列有缺失值的行:")
- print(name_na)
- # 选择Age列没有缺失值的行
- age_not_na = df_missing[df_missing['Age'].notna()]
- print("\nAge列没有缺失值的行:")
- print(age_not_na)
复制代码
删除含缺失值的行
使用dropna方法删除包含缺失值的行,可以根据需求选择不同的删除策略。
- # 删除任何包含缺失值的行
- drop_any_na = df_missing.dropna()
- print("删除任何包含缺失值的行:")
- print(drop_any_na)
- # 删除所有列都包含缺失值的行
- drop_all_na = df_missing.dropna(how='all')
- print("\n删除所有列都包含缺失值的行:")
- print(drop_all_na)
- # 删除特定列中包含缺失值的行
- drop_specific_na = df_missing.dropna(subset=['Name', 'Age'])
- print("\n删除Name和Age列中包含缺失值的行:")
- print(drop_specific_na)
- # 删除至少有两个缺失值的行
- drop_threshold_na = df_missing.dropna(thresh=3) # 保留至少有3个非缺失值的行
- print("\n删除至少有两个缺失值的行:")
- print(drop_threshold_na)
复制代码
填充缺失值后的行选择
使用fillna方法填充缺失值,然后进行行选择,这样可以保留更多的数据。
- # 用特定值填充缺失值
- filled_na = df_missing.fillna({'Name': 'Unknown', 'Age': 0, 'Salary': 0, 'Department': 'Unknown'})
- print("用特定值填充缺失值:")
- print(filled_na)
- # 用前一个值填充缺失值
- ffill_na = df_missing.fillna(method='ffill')
- print("\n用前一个值填充缺失值:")
- print(ffill_na)
- # 用后一个值填充缺失值
- bfill_na = df_missing.fillna(method='bfill')
- print("\n用后一个值填充缺失值:")
- print(bfill_na)
- # 用平均值填充数值列的缺失值
- filled_mean = df_missing.copy()
- filled_mean['Age'] = filled_mean['Age'].fillna(filled_mean['Age'].mean())
- filled_mean['Salary'] = filled_mean['Salary'].fillna(filled_mean['Salary'].mean())
- print("\n用平均值填充数值列的缺失值:")
- print(filled_mean)
- # 填充缺失值后选择特定行
- filled_selected = filled_mean[filled_mean['Age'] > 30]
- print("\n填充缺失值后选择年龄大于30的行:")
- print(filled_selected)
复制代码
排序后选择行
单列排序
使用sort_values方法按单列排序,可以快速找到最大值或最小值。
- # 按年龄升序排序
- age_asc = df.sort_values('Age')
- print("按年龄升序排序:")
- print(age_asc)
- # 按工资降序排序
- salary_desc = df.sort_values('Salary', ascending=False)
- print("\n按工资降序排序:")
- print(salary_desc)
复制代码
多列排序
使用sort_values方法按多列排序,可以实现更复杂的数据排序需求。
- # 创建一个更复杂的示例数据框
- data_complex = {
- 'Department': ['HR', 'IT', 'Finance', 'HR', 'IT', 'Finance', 'HR', 'IT'],
- 'Employee': ['Alice', 'Bob', 'Charlie', 'David', 'Eva', 'Frank', 'Grace', 'Henry'],
- 'Salary': [50000, 60000, 70000, 55000, 65000, 75000, 52000, 68000],
- 'Years_of_Service': [3, 5, 7, 2, 4, 8, 1, 6]
- }
- df_complex = pd.DataFrame(data_complex)
- # 按部门升序和工资降序排序
- dept_asc_salary_desc = df_complex.sort_values(['Department', 'Salary'], ascending=[True, False])
- print("按部门升序和工资降序排序:")
- print(dept_asc_salary_desc)
- # 按部门升序和服务年限降序排序
- dept_asc_years_desc = df_complex.sort_values(['Department', 'Years_of_Service'], ascending=[True, False])
- print("\n按部门升序和服务年限降序排序:")
- print(dept_asc_years_desc)
复制代码
排序后选择前N行
结合排序和head方法选择前N行,可以快速找到排名靠前的数据。
- # 选择工资最高的3名员工
- top_3_salary = df.sort_values('Salary', ascending=False).head(3)
- print("工资最高的3名员工:")
- print(top_3_salary)
- # 选择每个部门工资最高的员工
- top_salary_by_dept = df_complex.sort_values(['Department', 'Salary'], ascending=[True, False])\
- .groupby('Department')\
- .head(1)
- print("\n每个部门工资最高的员工:")
- print(top_salary_by_dept)
- # 选择服务年限最长的2名员工
- top_2_years = df_complex.sort_values('Years_of_Service', ascending=False).head(2)
- print("\n服务年限最长的2名员工:")
- print(top_2_years)
复制代码
分组后选择行
groupby基础
使用groupby方法对数据进行分组,可以实现分组统计和分析。
- # 按部门分组
- grouped_by_dept = df_complex.groupby('Department')
- print("按部门分组:")
- for name, group in grouped_by_dept:
- print(f"\n部门: {name}")
- print(group)
- # 计算每个部门的平均工资
- avg_salary_by_dept = df_complex.groupby('Department')['Salary'].mean()
- print("\n每个部门的平均工资:")
- print(avg_salary_by_dept)
复制代码
分组后选择特定组
使用get_group方法选择特定组,可以查看特定分组的详细信息。
- # 获取IT部门的员工
- it_dept = df_complex.groupby('Department').get_group('IT')
- print("IT部门的员工:")
- print(it_dept)
- # 获取HR部门的员工
- hr_dept = df_complex.groupby('Department').get_group('HR')
- print("\nHR部门的员工:")
- print(hr_dept)
复制代码
分组后应用聚合函数
使用agg方法应用多个聚合函数,可以实现更复杂的分组分析。
- # 计算每个部门的工资统计信息
- salary_stats_by_dept = df_complex.groupby('Department')['Salary'].agg(['mean', 'median', 'min', 'max'])
- print("每个部门的工资统计信息:")
- print(salary_stats_by_dept)
- # 计算每个部门的员工人数和服务年限统计
- dept_stats = df_complex.groupby('Department').agg({
- 'Employee': 'count',
- 'Salary': ['mean', 'max'],
- 'Years_of_Service': ['mean', 'min']
- })
- print("\n每个部门的员工人数和服务年限统计:")
- print(dept_stats)
- # 选择平均工资大于60000的部门
- high_salary_depts = df_complex.groupby('Department').filter(lambda x: x['Salary'].mean() > 60000)
- print("\n平均工资大于60000的部门:")
- print(high_salary_depts)
复制代码
链式操作提高效率
方法链的概念
方法链是指将多个方法调用连接在一起,每个方法都作用于前一个方法的结果。这样可以提高代码的可读性和效率。
- # 传统方式(多步骤)
- step1 = df.copy()
- step2 = step1[step1['Age'] > 30]
- step3 = step2.sort_values('Salary', ascending=False)
- result = step3.head(3)
- print("传统方式(多步骤):")
- print(result)
- # 链式操作
- chained_result = df.copy()[df['Age'] > 30].sort_values('Salary', ascending=False).head(3)
- print("\n链式操作:")
- print(chained_result)
复制代码
实例演示
通过实际案例演示链式操作的应用,展示其在复杂数据处理中的优势。
- # 创建一个更大的示例数据集
- np.random.seed(42)
- data_large = {
- 'ID': range(1, 101),
- 'Name': [f'Employee_{i}' for i in range(1, 101)],
- 'Department': np.random.choice(['HR', 'IT', 'Finance', 'Marketing', 'Operations'], 100),
- 'Salary': np.random.randint(40000, 120000, 100),
- 'Years_of_Service': np.random.randint(1, 15, 100),
- 'Performance_Score': np.random.uniform(1, 5, 100).round(1)
- }
- df_large = pd.DataFrame(data_large)
- # 使用链式操作找出IT部门中绩效评分大于4.0且服务年限超过5年的前5名最高薪员工
- top_it_performers = df_large[
- (df_large['Department'] == 'IT') &
- (df_large['Performance_Score'] > 4.0) &
- (df_large['Years_of_Service'] > 5)
- ].sort_values('Salary', ascending=False).head(5)
- print("IT部门中绩效评分大于4.0且服务年限超过5年的前5名最高薪员工:")
- print(top_it_performers)
- # 使用链式操作计算每个部门的平均工资,然后选择平均工资大于70000的部门
- high_avg_salary_depts = df_large.groupby('Department')['Salary'].mean().reset_index()
- high_avg_salary_depts = high_avg_salary_depts[high_avg_salary_depts['Salary'] > 70000]
- print("\n平均工资大于70000的部门:")
- print(high_avg_salary_depts)
- # 使用链式操作找出每个部门中绩效评分最高的员工
- top_performers_by_dept = df_large.sort_values(['Department', 'Performance_Score'], ascending=[True, False])\
- .groupby('Department')\
- .head(1)\
- .sort_values('Performance_Score', ascending=False)
- print("\n每个部门中绩效评分最高的员工:")
- print(top_performers_by_dept)
复制代码
性能优化技巧
避免循环
使用向量化操作代替循环可以显著提高性能,特别是在处理大型数据集时。
- # 创建一个大型数据框
- np.random.seed(42)
- df_perf = pd.DataFrame({
- 'A': np.random.rand(100000),
- 'B': np.random.rand(100000),
- 'C': np.random.rand(100000)
- })
- # 使用循环计算新列(不推荐)
- df_perf['D_loop'] = 0.0
- for i in range(len(df_perf)):
- df_perf.loc[i, 'D_loop'] = df_perf.loc[i, 'A'] + df_perf.loc[i, 'B'] * df_perf.loc[i, 'C']
- # 使用向量化操作(推荐)
- df_perf['D_vectorized'] = df_perf['A'] + df_perf['B'] * df_perf['C']
- # 验证结果是否相同
- print("结果是否相同:", (df_perf['D_loop'] == df_perf['D_vectorized']).all())
复制代码
使用向量化操作
向量化操作是pandas中提高性能的关键,可以大幅提高数据处理速度。
- # 创建一个大型数据框
- np.random.seed(42)
- df_vector = pd.DataFrame({
- 'ID': range(1, 100001),
- 'Value': np.random.rand(100000),
- 'Category': np.random.choice(['A', 'B', 'C', 'D'], 100000)
- })
- # 使用向量化操作过滤数据
- filtered_vector = df_vector[df_vector['Value'] > 0.5]
- # 使用iterrows进行过滤(不推荐)
- filtered_iter = pd.DataFrame(columns=df_vector.columns)
- for index, row in df_vector.iterrows():
- if row['Value'] > 0.5:
- filtered_iter = pd.concat([filtered_iter, pd.DataFrame([row])], ignore_index=True)
- # 使用apply进行过滤(不推荐)
- filtered_apply = df_vector[df_vector.apply(lambda x: x['Value'] > 0.5, axis=1)]
- print("向量化操作结果行数:", len(filtered_vector))
- print("iterrows操作结果行数:", len(filtered_iter))
- print("apply操作结果行数:", len(filtered_apply))
复制代码
使用eval方法提高性能
eval方法可以提高复杂表达式计算的效率,特别是在处理大型数据集时。
- # 创建一个大型数据框
- np.random.seed(42)
- df_eval = pd.DataFrame({
- 'A': np.random.rand(100000),
- 'B': np.random.rand(100000),
- 'C': np.random.rand(100000),
- 'D': np.random.rand(100000)
- })
- # 使用传统方式计算
- result_traditional = df_eval['A'] + df_eval['B'] * df_eval['C'] - df_eval['D'] / (df_eval['A'] + 1)
- # 使用eval方法计算
- result_eval = df_eval.eval('A + B * C - D / (A + 1)')
- # 验证结果是否相同
- print("结果是否相同:", np.allclose(result_traditional, result_eval))
- # 使用eval方法进行过滤
- filtered_eval = df_eval[df_eval.eval('(A > 0.5) & (B < 0.5) | (C > 0.8)')]
- # 使用传统方式过滤
- filtered_traditional = df_eval[(df_eval['A'] > 0.5) & (df_eval['B'] < 0.5) | (df_eval['C'] > 0.8)]
- # 验证结果是否相同
- print("过滤结果是否相同:", filtered_eval.equals(filtered_traditional))
复制代码
实际案例分析
案例一:销售数据分析
假设我们有一个包含销售数据的DataFrame,我们需要分析不同产品在不同地区的销售情况。
- # 创建销售数据
- np.random.seed(42)
- sales_data = {
- 'Date': pd.date_range(start='2023-01-01', end='2023-12-31', freq='D'),
- 'Product': np.random.choice(['Laptop', 'Smartphone', 'Tablet', 'Monitor', 'Keyboard'], 365),
- 'Region': np.random.choice(['North', 'South', 'East', 'West'], 365),
- 'Sales': np.random.randint(100, 1000, 365),
- 'Revenue': np.random.randint(10000, 100000, 365)
- }
- df_sales = pd.DataFrame(sales_data)
- # 分析1:找出每个地区销售额最高的产品
- best_product_by_region = df_sales.groupby(['Region', 'Product'])['Sales'].sum().reset_index()
- best_product_by_region = best_product_by_region.sort_values(['Region', 'Sales'], ascending=[True, False])
- best_product_by_region = best_product_by_region.groupby('Region').head(1)
- print("每个地区销售额最高的产品:")
- print(best_product_by_region)
- # 分析2:找出每个月销售额最高的3天
- df_sales['Month'] = df_sales['Date'].dt.month
- top_3_days_by_month = df_sales.sort_values(['Month', 'Sales'], ascending=[True, False]).groupby('Month').head(3)
- print("\n每个月销售额最高的3天:")
- print(top_3_days_by_month[['Date', 'Month', 'Sales']].head(15)) # 只显示前15行
- # 分析3:找出销售额超过平均值且收入超过平均值的产品
- avg_sales = df_sales['Sales'].mean()
- avg_revenue = df_sales['Revenue'].mean()
- high_performers = df_sales[(df_sales['Sales'] > avg_sales) & (df_sales['Revenue'] > avg_revenue)]
- print(f"\n销售额超过平均值({avg_sales:.2f})且收入超过平均值({avg_revenue:.2f})的产品:")
- print(high_performers.head(10)) # 只显示前10行
- # 分析4:找出每个地区每个季度的销售趋势
- df_sales['Quarter'] = df_sales['Date'].dt.quarter
- quarterly_sales_by_region = df_sales.groupby(['Region', 'Quarter'])['Sales'].sum().unstack()
- print("\n每个地区每个季度的销售趋势:")
- print(quarterly_sales_by_region)
复制代码
案例二:时间序列数据处理
假设我们有一个包含股票价格的时间序列数据,我们需要分析股票价格的变化趋势。
- # 创建股票价格数据
- np.random.seed(42)
- dates = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D')
- price_changes = np.random.normal(0, 1, len(dates)) # 随机价格变化
- prices = [100] # 初始价格
- for change in price_changes:
- prices.append(prices[-1] * (1 + change/100)) # 计算新价格
-
- stock_data = {
- 'Date': dates,
- 'Price': prices[1:], # 去掉初始价格
- 'Volume': np.random.randint(10000, 100000, len(dates))
- }
- df_stock = pd.DataFrame(stock_data)
- # 分析1:找出价格涨幅最大的5天
- df_stock['Price_Change'] = df_stock['Price'].pct_change() * 100 # 计算价格变化百分比
- top_5_gains = df_stock.sort_values('Price_Change', ascending=False).head(5)
- print("价格涨幅最大的5天:")
- print(top_5_gains[['Date', 'Price', 'Price_Change']])
- # 分析2:找出交易量最大的10天
- top_10_volume = df_stock.sort_values('Volume', ascending=False).head(10)
- print("\n交易量最大的10天:")
- print(top_10_volume[['Date', 'Volume']])
- # 分析3:计算并绘制30天移动平均线
- df_stock['MA_30'] = df_stock['Price'].rolling(window=30).mean()
- # 找出价格高于30天移动平均线的天数
- above_ma = df_stock[df_stock['Price'] > df_stock['MA_30']]
- print(f"\n价格高于30天移动平均线的天数: {len(above_ma)}")
- print(f"占总天数的比例: {len(above_ma)/len(df_stock)*100:.2f}%")
- # 分析4:找出价格波动最大的月份
- df_stock['Month'] = df_stock['Date'].dt.month
- monthly_volatility = df_stock.groupby('Month')['Price_Change'].std().reset_index()
- monthly_volatility = monthly_volatility.sort_values('Price_Change', ascending=False)
- print("\n价格波动最大的月份:")
- print(monthly_volatility)
- # 分析5:找出价格连续上涨超过5天的期间
- df_stock['Price_Direction'] = np.where(df_stock['Price_Change'] > 0, 1, 0)
- df_stock['Consecutive_Days'] = df_stock['Price_Direction'] * (df_stock['Price_Direction'].groupby((df_stock['Price_Direction'] != df_stock['Price_Direction'].shift()).cumsum()).cumcount() + 1)
- long_streaks = df_stock[df_stock['Consecutive_Days'] >= 5]
- print("\n价格连续上涨超过5天的期间:")
- print(long_streaks[['Date', 'Price', 'Price_Change', 'Consecutive_Days']])
复制代码
总结与最佳实践
在本文中,我们详细介绍了Python pandas库中高效输出数据行的各种技巧和方法。从基础的行选择方法到高级的过滤技巧,我们涵盖了数据框行操作的各个方面。以下是一些关键要点和最佳实践:
1. 选择合适的方法:使用loc和iloc进行基于标签和位置的行选择使用head和tail快速查看数据的前几行和后几行使用sample进行随机抽样
2. 使用loc和iloc进行基于标签和位置的行选择
3. 使用head和tail快速查看数据的前几行和后几行
4. 使用sample进行随机抽样
5. 高效过滤数据:使用布尔条件进行单条件和多条件过滤使用query方法简化复杂的过滤条件使用isin、str方法和正则表达式进行高级过滤
6. 使用布尔条件进行单条件和多条件过滤
7. 使用query方法简化复杂的过滤条件
8. 使用isin、str方法和正则表达式进行高级过滤
9. 处理缺失值:使用isna和notna检测缺失值使用dropna删除包含缺失值的行使用fillna填充缺失值
10. 使用isna和notna检测缺失值
11. 使用dropna删除包含缺失值的行
12. 使用fillna填充缺失值
13. 排序和分组:使用sort_values对数据进行排序使用groupby对数据进行分组分析结合排序和分组操作获取特定数据子集
14. 使用sort_values对数据进行排序
15. 使用groupby对数据进行分组分析
16. 结合排序和分组操作获取特定数据子集
17. 提高性能:使用链式操作提高代码可读性和效率避免使用循环,改用向量化操作使用eval方法提高复杂表达式计算的效率
18. 使用链式操作提高代码可读性和效率
19. 避免使用循环,改用向量化操作
20. 使用eval方法提高复杂表达式计算的效率
21. 实际应用:将所学技巧应用于实际数据分析案例根据具体需求选择合适的方法和技巧不断练习和探索新的数据处理方法
22. 将所学技巧应用于实际数据分析案例
23. 根据具体需求选择合适的方法和技巧
24. 不断练习和探索新的数据处理方法
选择合适的方法:
• 使用loc和iloc进行基于标签和位置的行选择
• 使用head和tail快速查看数据的前几行和后几行
• 使用sample进行随机抽样
高效过滤数据:
• 使用布尔条件进行单条件和多条件过滤
• 使用query方法简化复杂的过滤条件
• 使用isin、str方法和正则表达式进行高级过滤
处理缺失值:
• 使用isna和notna检测缺失值
• 使用dropna删除包含缺失值的行
• 使用fillna填充缺失值
排序和分组:
• 使用sort_values对数据进行排序
• 使用groupby对数据进行分组分析
• 结合排序和分组操作获取特定数据子集
提高性能:
• 使用链式操作提高代码可读性和效率
• 避免使用循环,改用向量化操作
• 使用eval方法提高复杂表达式计算的效率
实际应用:
• 将所学技巧应用于实际数据分析案例
• 根据具体需求选择合适的方法和技巧
• 不断练习和探索新的数据处理方法
通过掌握这些技巧和方法,你可以更加高效地处理和分析数据,提高数据分析的效率和准确性。无论是处理小型数据集还是大型数据集,这些技巧都能帮助你快速获取所需的数据行,为后续的分析和决策提供支持。
在实际应用中,建议根据数据的特点和分析的需求,灵活选择和组合不同的方法。同时,也要注意代码的可读性和可维护性,编写清晰、简洁的代码,以便于自己和他人理解和维护。
最后,数据分析是一个不断学习和探索的过程,希望本文提供的技巧和方法能帮助你更好地使用pandas库进行数据分析工作。 |
|