Pandas处理宽格式社交媒体数据:转长格式及频率占比可视化
宽格式转长格式及可视化解决方案
1. 数据宽转长处理
你的数据属于成对组列结构,用pd.wide_to_long比多次melt更高效,能直接把SNS使用标记和对应频率列配对,避免手动合并的麻烦。
假设你的DataFrame名为df,列名是Id, SNS1, SNS2, SNS3, SNS4, SNS5, Freq1, Freq2, Freq3, Freq4, Freq5,执行以下代码:
import pandas as pd # 一步转长格式,自动配对SNS和Freq列 long_df = pd.wide_to_long(df, stubnames=['SNS', 'Freq'], # 两组列的前缀 i='Id', # 用户唯一标识列 j='sns_index', # 生成的新列,标记SNS序号 sep='') # 列名前缀和数字无分隔符,设为空 # 重置索引,把序号转为普通列 long_df = long_df.reset_index() # 过滤掉未使用该SNS的行(仅保留SNS值为1的记录) long_df = long_df[long_df['SNS'] == 1].drop(columns=['SNS']) # 给序号替换成易读的社交媒体名称(根据你的实际情况修改映射关系) long_df['sns_name'] = long_df['sns_index'].map({ 1: '微信', 2: '微博', 3: '抖音', 4: '小红书', 5: 'B站' })
如果坚持要用melt,可以分两次转换再合并:
# 转换SNS使用标记列 sns_melt = df.melt( id_vars=['Id'], value_vars=['SNS1','SNS2','SNS3','SNS4','SNS5'], var_name='sns_col', value_name='is_used' ) # 转换频率列 freq_melt = df.melt( id_vars=['Id'], value_vars=['Freq1','Freq2','Freq3','Freq4','Freq5'], var_name='freq_col', value_name='frequency' ) # 提取列名中的数字,用来配对SNS和Freq sns_melt['sns_index'] = sns_melt['sns_col'].str.extract('(\d+)').astype(int) freq_melt['sns_index'] = freq_melt['freq_col'].str.extract('(\d+)').astype(int) # 合并两张表,过滤未使用的记录 long_df = pd.merge(sns_melt, freq_melt, on=['Id', 'sns_index']) long_df = long_df[long_df['is_used'] == 1].drop(columns=['sns_col', 'freq_col', 'is_used']) # 替换为易读名称 long_df['sns_name'] = long_df['sns_index'].map({ 1: '微信', 2: '微博', 3: '抖音', 4: '小红书', 5: 'B站' })
转换后long_df为标准长格式:每行对应一个用户的一个已使用社交媒体及其频率,列包含Id, sns_index, frequency, sns_name。
2. 绘制使用频率占比图表
用seaborn和matplotlib实现两种常见的占比可视化:
堆叠条形图(展示单个社交媒体内的频率分布)
import seaborn as sns import matplotlib.pyplot as plt # 统计各社交媒体的频率计数,计算占比 freq_stats = long_df.groupby(['sns_name', 'frequency']).size().unstack(fill_value=0) freq_pct = freq_stats.div(freq_stats.sum(axis=1), axis=0) * 100 # 绘制堆叠图 freq_pct.plot(kind='bar', stacked=True, figsize=(10,6)) plt.title('各社交媒体使用频率占比') plt.xlabel('社交媒体') plt.ylabel('占比 (%)') plt.legend(title='使用频率') plt.xticks(rotation=0) plt.tight_layout() plt.show()
分组条形图(对比不同社交媒体的同频率占比)
# 转换数据格式适配seaborn freq_pct_melt = freq_pct.reset_index().melt( id_vars='sns_name', var_name='frequency', value_name='percentage' ) # 绘制分组条形图 sns.barplot(data=freq_pct_melt, x='sns_name', y='percentage', hue='frequency') plt.title('各社交媒体使用频率占比') plt.xlabel('社交媒体') plt.ylabel('占比 (%)') plt.legend(title='使用频率') plt.tight_layout() plt.show()
关键注意事项
- 如果
frequency列的N/A是无效值,可提前过滤:long_df = long_df[long_df['frequency'] != 'N/A'] - 务必替换
sns_name的映射关系为实际社交媒体名称,提升图表可读性 - 若数据量较大,统计时要确保分组逻辑正确,避免重复或遗漏用户记录
内容的提问来源于stack exchange,提问作者Ali Abdullah
相关产品推荐
相关产品推荐

