categorical_data(类别型数据)预处理笔记:转化为数字

本文介绍如何使用Python和R语言进行数据预处理,包括读取文件、转换数据类型、处理异常值等步骤。针对具体数据集如Soybean,提供详细的代码实现。

 

1、用Python转化为标准格式。

import pandas as pd
import numpy as np
from pandas import Series, DataFrame
from sklearn.preprocessing import LabelEncoder

#一般操作
#读文件:
#e:/cate_data/before/filename.txt
#1将文件读入成Dataframe数据。分隔符默认为"\t",读的时候文件中无列名(否则把第一行作为列名)。
data = pd.read_table('old_path',',',header = None)
#2类别型数据转化为数字表示。
num = data.shape[1]
for i in range(num):
    dimensional_name = data.columns[i]#第i个维度的列名。
    data[dimensional_name] = LabelEncoder().fit_transform(data[dimensional_name].values)#转化
#3将DataFrame数据写入文件。写的时候不要索引和标题。
data.to_csv('new_path',index=False,header=None)

#附加操作
data = data.drop(data.columns[1],axis = 1) #去掉第1(二)行。
length = len(data[data.columns[2]][0].split()[0])#字符串长度
data1 = DataFrame(columns=range(length))#初始化一个空的DataFrame。
for i in range(data[data.columns[1]].shape[0]):
    a = list(data[data.columns[1]][i].split())
    b = list(a[0])
    # 将字典输入给DataFrame构造器,各项会成为DataFrame的一行,字典健将成为DataFrame的列标
    dashabi = dict(zip(list(range(length)),b))
    dashabi1 = DataFrame(dashabi,index=[0])
    # 往DataFrame添加行的方式(gnore_index=True表示去掉原来的行标,重新开始编排)
    data1= data1.append(dashabi1,ignore_index=True)
    # pd.concat([data1, dashabi1, dashabi2, ...], ignore_index=True)(第二种)
data = data.drop(data.columns[1],axis = 1) #去掉第1(二)行。
data1 = pd.concat([data1,data],axis =1,ignore_index=True)#axis默认为0,列拼接。
data = data1

#额外操作
del data[0] #删除第0列,删除后列编号就没有0了。
data.columns = range(10) #给列重新编号。
data.dtypes  #查看每一列的数据类型。

输出:
0     int64
1     int64
2     int64
3     int64
4     int64
5    object #第五列含有异常值'?'。
6     int64
7     int64
8     int64
9     int64
dtype: object

#去除含有异常值的行
#1统计含有异常值的行。
j = []
for i in range(699):
    if(data[5][i] == '?'): #是字符。
        j.append(i)
#2删除行。
data = data.drop(j)
#3行重新编号。
data.index = range(len(data.index))
#4将类型转化为int64。
data[5] = pd.to_numeric(data[5])

#查看每一列的数据类型。
data.dtypes 
输出:
0     int64
1     int64
2     int64
3     int64
4     int64
5     int64 #转化完毕。
6     int64
7     int64
8     int64
9     int64
dtype: object

#mushroom(替换缺失值(异常值'?'))。
#1读入。
data = pd.read_table('e:/lxt/cate_data/before/mushroom.txt',',',header = None)
#2统计含有异常值的列。
l = []
for i in range(data.shape[1]):
    if '?' in pd.unique(data[i]):
        l.append(i)
#3随机替换异常值为值域中的值。
for i in l:
    #生成值域(pd.unique返回类型为numpy.ndarray)。
    hahaha = pd.unique(data[i])['?' != pd.unique(data[i])]
    for j in range(data.shape[0]):
        if(data[i][j] == '?'):
            #随机从值域挑选替换。
            data[i][j] = hahaha[np.random.randint(0,hahaha.shape[0])]
#转化为连续数字。
for i in range(data.shape[1]):
    dimensional_name = data.columns[i]#第i个维度的列名。
    data[dimensional_name] = LabelEncoder().fit_transform(data[dimensional_name].values)
#将类别换到最后。
label = data[0].copy()
del data[0]
data = pd.concat([data,label],axis =1,ignore_index=True)
#输出。
data.to_csv('e:/lxt/cate_data/after/mushroom.txt',index=False,header=None)
data.to_csv('e:/lxt/cate_data/after/mushroom.csv',index=False,header=None)
        

数据:UCI数据集:Soybean(small),Connect4,Promoters。

需要进行附加操作的数据:Promoters:

+,S10,		tactagcaatacgcttgcgttcggtggttaagtatgtataatgcgcgggcttgtcgt
+,AMPC,		tgctatcctgacagttgtcacgctgattggtgtcgttacaatctaacgcatcgccaa
+,AROH,		gtactagagaactagtgcattagcttatttttttgttatcatgctaaccacccggcg
+,DEOP2,	aattgtgatgtgtatcgaagtgtgttgcggagtagatgttagaatactaacaaactc
+,LEU1_TRNA,	tcgataattaactattgacgaaaagctgaaaaccactagaatgcgcctccgtggtag
+,MALEFG,	aggggcaaggaggatggaaagaggttgccgtataaagaaactagagtccgtttaggt
+,MALK,		cagggggtggaggatttaagccatctcctgatgacgcatagtcagcccatcatgaat
+,RECA,		tttctacaaaacacttgatactgtatgagcatacagtataattgcttcaacagaaca
+,RPOB,		cgacttaatatactgcgacaggacgtccgttctgtgtaaatcgcaatgaaatggttt
+,RRNAB_P1,	ttttaaatttcctcttgtcaggccggaataactccctataatgcgccaccactgaca
+,RRNAB_P2,	gcaaaaataaatgcttgactctgtagcgggaaggcgtattatgcacaccccgcgccg
+,RRNDEX_P2,	cctgaaattcagggttgactctgaaagaggaaagcgtaatatacgccacctcgcgac
+,RRND_P1,	gatcaaaaaaatacttgtgcaaaaaattgggatccctataatgcgcctccgttgaga
+,RRNE_P1,	ctgcaatttttctattgcggcctgcggagaactccctataatgcgcctccatcgaca
+,RRNG_P1,	tttatatttttcgcttgtcaggccggaataactccctataatgcgccaccactgaca
+,RRNG_P2,	aagcaaagaaatgcttgactctgtagcgggaaggcgtattatgcacaccgccgcgcc
+,RRNX_P1,	atgcatttttccgcttgtcttcctgagccgactccctataatgcgcctccatcgaca
+,TNAA,		aaacaatttcagaatagacaaaaactctgagtgtaataatgtagcctcgtgtcttgc
+,TYRT,		tctcaacgtaacactttacagcggcgcgtcatttgatatgatgcgccccgcttcccg
+,ARAC,		gcaaataatcaatgtggacttttctgccgtgattatagacacttttgttacgcgttt
+,LACI,		gacaccatcgaatggcgcaaaacctttcgcggtatggcatgatagcgcccggaagag
+,MALT,		aaaaacgtcatcgcttgcattagaaaggtttctggccgaccttataaccattaatta
+,TRP,		tctgaaatgagctgttgacaattaatcatcgaactagttaactagtacgcaagttca
+,TRPP2,	accggaagaaaaccgtgacattttaacacgtttgttacaaggtaaaggcgacgccgc
+,THR,		aaattaaaattttattgacttaggtcactaaatactttaaccaatataggcatagcg
+,BIOB,		ttgtcataatcgacttgtaaaccaaattgaaaagatttaggtttacaagtctacacc
+,FOL,		catcctcgcaccagtcgacgacggtttacgctttacgtatagtggcgacaatttttt
+,UVRBP1,	tccagtataatttgttggcataattaagtacgacgagtaaaattacatacctgcccg
+,UVRBP3,	acagttatccactattcctgtggataaccatgtgtattagagttagaaaacacgagg
+,LEXA,		tgtgcagtttatggttccaaaatcgccttttgctgtatatactcacagcataactgt
+,PORI-L,	ctgttgttcagtttttgagttgtgtataacccctcattctgatcccagcttatacgg
+,SPOT42,	attacaaaaagtgctttctgaactgaacaaaaaagagtaaagttagtcgcgtagggt
+,M1RNA,	atgcgcaacgcggggtgacaagggcgcgcaaaccctctatactgcgcgccgaagctg
+,GLNS,		taaaaaactaacagttgtcagcctgtcccgcttataagatcatacgccgttatacgt
+,TUFB,		atgcaattttttagttgcatgaactcgcatgtctccatagaatgcgcgctacttgat
+,SUBB-E,	ccttgaaaaagaggttgacgctgcaaggctctatacgcataatgcgccccgcaacgc
+,STR,		tcgttgtatatttcttgacaccttttcggcatcgccctaaaattcggcgtcctcata
+,SPC,		ccgtttattttttctacccatatccttgaagcggtgttataatgccgcgccctcgat
+,RPOA,		ttcgcatatttttcttgcaaagttgggttgagctggctagattagccagccaatctt
+,RPLJ,		tgtaaactaatgcctttacgtgggcggtgattttgtctacaatcttacccccacgta
+,PORI-R,	gatcgcacgatctgtatacttatttgagtaaattaacccacgatcccagccattctt
+,ALAS,		aacgcatacggtattttaccttcccagtcaagaaaacttatcttattcccacttttc
+,ARABAD,	ttagcggatcctacctgacgctttttatcgcaactctctactgtttctccatacccg
+,BIOA,		gccttctccaaaacgtgttttttgttgttaattcggtgtagacttgtaaacctaaat
+,DEOP1,	cagaaacgttttattcgaacatcgatctcgtcttgtgttagaattctaacatacggt
+,GALP2,	cactaatttattccatgtcacacttttcgcatctttgttatgctatggttatttcat
+,HIS,		atataaaaaagttcttgctttctaacgtgaaagtggtttaggttaaaagacatcagt
+,HISJ,		caaggtagaatgctttgccttgtcggcctgattaatggcacgatagtcgcatcggat
+,ILVGEDA,	ggccaaaaaatatcttgtactatttacaaaacctatggtaactctttaggcattcct
+,LACP1,	taggcaccccaggctttacactttatgcttccggctcgtatgttgtgtggaattgtg
+,LPP,		ccatcaaaaaaatattctcaacataaaaaactttgtgtaatacttgtaacgctacat
+,TRPR,		tggggacgtcgttactgatccgcacgtttatgatatgctatcgtactctttagcgag
+,UVRB_P2,	tcagaaatattatggtgatgaactgtttttttatccagtataatttgttggcataat
-, 867,		atatgaacgttgagactgccgctgagttatcagctgtgaacgacattctggcgtcta
-,1169,		cgaacgagtcaatcagaccgctttgactctggtattactgtgaacattattcgtctc
-, 802,		caatggcctctaaacgggtcttgaggggttttttgctgaaaggaggaactatatgcg
-, 521,		ttgacctactacgccagcattttggcggtgtaagctaaccattccggttgactcaat
-, 918,		cgtctatcggtgaacctccggtatcaacgctggaaggtgacgctaacgcagatgcag
-,1481,		gccaatcaatcaagaacttgaagggtggtatcagccaacagcctgacatccttcgtt
-,1024,		tggatggacgttcaacattgaggaaggcataacgctactacctgatgtttactccaa
-,1149,		gaggtggctatgtgtatgaccgaacgagtcaatcagaccgctttgactctggtatta
-, 313,		cgtagcgcatcagtgctttcttactgtgagtacgcaccagcgccagaggacgacgac
-, 780,		cgaccgaagcgagcctcgtcctcaatggcctctaaacgggtcttgaggggttttttg
-,1384,		ctacggtgggtacaatatgctggatggagatgcgttcacttctggtctactgactcg
-, 507,		atagtctcagagtcttgacctactacgccagcattttggcggtgtaagctaaccatt
-,  39,		aactcaaggctgatacggcgagacttgcgagccttgtccttgcggtacacagcagcg
-,1203,		ttactgtgaacattattcgtctccgcgactacgatgagatgcctgagtgcttccgtt
-, 988,		tattctcaacaagattaaccgacagattcaatctcgtggatggacgttcaacattga
-,1171,		aacgagtcaatcagaccgctttgactctggtattactgtgaacattattcgtctccg
-, 753,		aagtgcttagcttcaaggtcacggatacgaccgaagcgagcctcgtcctcaatggcc
-, 630,		gaagaccacgcctcgccaccgagtagacccttagagagcatgtcagcctcgacaact
-, 660,		ttagagagcatgtcagcctcgacaacttgcataaatgctttcttgtagacgtgccct
-,1216,		tattcgtctccgcgactacgatgagatgcctgagtgcttccgttactggattgtcac
-, 835,		tgctgaaaggaggaactatatgcgctcatacgatatgaacgttgagactgccgctga
-,  35,		catgaactcaaggctgatacggcgagacttgcgagccttgtccttgcggtacacagc
-,1218,		ttcgtctccgcgactacgatgagatgcctgagtgcttccgttactggattgtcacca
-, 668,		catgtcagcctcgacaacttgcataaatgctttcttgtagacgtgccctacgcgctt
-, 413,		aggaggaactacgcaaggttggaacatcggagagatgccagccagcgcacctgcacg
-, 991,		tctcaacaagattaaccgacagattcaatctcgtggatggacgttcaacattgagga
-, 751,		tgaagtgcttagcttcaaggtcacggatacgaccgaagcgagcctcgtcctcaatgg
-, 850,		ctatatgcgctcatacgatatgaacgttgagactgccgctgagttatcagctgtgaa
-,  93,		gcggcagcacgtttccacgcggtgagagcctcaggattcatgtcgatgtcttccggt
-,1108,		atccctaatgtctacttccggtcaatccatctacgttaaccgaggtggctatgtgta
-, 915,		tggcgtctatcggtgaacctccggtatcaacgctggaaggtgacgctaacgcagatg
-,1019,		tctcgtggatggacgttcaacattgaggaaggcataacgctactacctgatgtttac
-,  19,		tattggcttgctcaagcatgaactcaaggctgatacggcgagacttgcgagccttgt
-,1320,		tagagggtgtactccaagaagaggaagatgaggctagacgtctctgcatggagtatg
-,  91,		cagcggcagcacgtttccacgcggtgagagcctcaggattcatgtcgatgtcttccg
-, 217,		ttacgttggcgaccgctaggactttcttgttgattttccatgcggtgttttgcgcaa
-, 957,		acgctaacgcagatgcagcgaacgctcggcgtattctcaacaagattaaccgacaga
-, 260,		ggtgttttgcgcaatgttaatcgctttgtacacctcaggcatgtaaacgtcttcgta
-, 557,		aaccattccggttgactcaatgagcatctcgatgcagcgtactcctacatgaataga
-,1355,		agacgtctctgcatggagtatgagatggactacggtgggtacaatatgctggatgga
-, 244,		tgttgattttccatgcggtgttttgcgcaatgttaatcgctttgtacacctcaggca
-, 464,		tgcacgggttgcgatagcctcagcgtattcaggtgcgagttcgatagtctcagagtc
-, 296,		aggcatgtaaacgtcttcgtagcgcatcagtgctttcttactgtgagtacgcaccag
-, 648,		ccgagtagacccttagagagcatgtcagcctcgacaacttgcataaatgctttcttg
-, 230,		cgctaggactttcttgttgattttccatgcggtgttttgcgcaatgttaatcgcttt
-,1163,		tatgaccgaacgagtcaatcagaccgctttgactctggtattactgtgaacattatt
-,1321,		agagggtgtactccaagaagaggaagatgaggctagacgtctctgcatggagtatga
-, 663,		gagagcatgtcagcctcgacaacttgcataaatgctttcttgtagacgtgccctacg
-, 799,		cctcaatggcctctaaacgggtcttgaggggttttttgctgaaaggaggaactatat
-, 987,		gtattctcaacaagattaaccgacagattcaatctcgtggatggacgttcaacattg
-,1226,		cgcgactacgatgagatgcctgagtgcttccgttactggattgtcaccaaggcttcc
-, 794,		ctcgtcctcaatggcctctaaacgggtcttgaggggttttttgctgaaaggaggaac
-,1442,		taacattaataaataaggaggctctaatggcactcattagccaatcaatcaagaact

 2、用R语言读入。

#函数(自己写)
read_data <- function(file_path,header = FALSE){
    data_list = read.csv(file = file_path,header = header)
    dimensional_num = length(data_list)
    data_num = length(data_list[[1]])
    dataset = list()
    data_set = matrix(0,dimensional_num-1,data_num)
    for (i in 1:(dimensional_num-1)) {
        data_set[i,] = data_list[[i]]
    }
    dataset$data = data_set
    dataset$label = data_list[[dimensional_num]]
    dataset$hidden_clusters = Hidden_clusters(dataset$label)
    return(dataset)
}
#label生成(原分类)
Hidden_clusters <- function(data_labels){
    uni = unique(data_labels)
    num = length(data_labels)
    hidden_clusters = list()
    i = 1
    for(j in uni){
        hidden_clusters[[i]] = (1:num)[data_labels == j]
        i = i + 1
    }
    return(hidden_clusters)
}
#读入(例子)
Soybean = read_data(file_path = "e:\\lxt\\cate_data\\after\\soybean.txt")

 

# 使用本机环境的消费者聚类分析项目 当然可以直接使用本机环境!这样更简单直接。以下是完整的项目代码: ## 🎯 **环境准备** ### **检查本机环境** ```bash # 检查Python版本 python --version # 检查必要包是否已安装 python -c "import pandas, numpy, sklearn; print('所有包已安装')" ``` ### **安装必要包(如需要)** ```bash pip install pandas numpy scikit-learn ``` ## 📁 **项目结构** ``` pythonProject1/ ├── data/ │ ├── raw/consume1.csv # 原始数据 │ ├── processed/ # 处理中的数据 │ └── final/ # 最终结果数据 ├── src/ │ └── consume.py # 主分析脚本 ├── results/ # 分析结果 └── README.md # 项目说明 ``` ## 🔧 **完整分析代码** ### **在 `src/consume.py` 中:** ```python # src/consume.py - 本机环境消费者聚类分析 import pandas as pd import numpy as np from sklearn.cluster import KMeans from sklearn.preprocessing import StandardScaler from sklearn.metrics import silhouette_score import os from datetime import datetime def setup_project(): """创建项目目录结构""" print("=== 项目初始化 ===") directories = [ 'data/raw', 'data/processed', 'data/final', 'src', 'results', 'notebooks' ] for directory in directories: os.makedirs(directory, exist_ok=True) print(f"✅ 目录就绪: {directory}") def check_dependencies(): """检查依赖包""" print("\n=== 环境检查 ===") try: import pandas as pd import numpy as np from sklearn.cluster import KMeans print(f"✅ pandas 版本: {pd.__version__}") print(f"✅ numpy 版本: {np.__version__}") print("✅ scikit-learn 可用") return True except ImportError as e: print(f"❌ 缺少依赖包: {e}") print("请运行: pip install pandas numpy scikit-learn") return False def load_data(): """加载数据""" print("\n=== 数据加载 ===") data_file = 'data/raw/consume1.csv' if not os.path.exists(data_file): print(f"❌ 数据文件不存在: {data_file}") print("请将 consume1.csv 文件放入 data/raw/ 目录") return None try: df = pd.read_csv(data_file) print(f"✅ 数据加载成功: {len(df)} 行, {len(df.columns)} 列") return df except Exception as e: print(f"❌ 数据加载失败: {e}") return None def explore_data(df): """数据探索""" print("\n=== 数据探索 ===") print(f"📊 数据维度: {df.shape[0]} 行 × {df.shape[1]} 列") print(f"\n📋 字段列表:") for i, col in enumerate(df.columns, 1): dtype = df[col].dtype unique_count = df[col].nunique() print(f" {i:2d}. {col} ({dtype}) - {unique_count} 个唯一值") # 数据质量快速检查 missing_count = df.isnull().sum().sum() duplicate_count = df.duplicated().sum() print(f"\n✅ 数据质量报告:") print(f" 缺失值: {missing_count} 个") print(f" 重复行: {duplicate_count} 个") if missing_count == 0 and duplicate_count == 0: print(" 🎉 数据质量优秀,无需预处理") return df def create_features(df): """特征工程""" print("\n=== 特征工程 ===") feature_columns = [] # 1. 直接使用所有数值字段 numeric_cols = df.select_dtypes(include=[np.number]).columns.tolist() feature_columns.extend(numeric_cols) print(f"✅ 数值特征: {len(numeric_cols)}个") # 2. 分类字段编码 categorical_cols = df.select_dtypes(include=['object']).columns.tolist() for col in categorical_cols: # 创建虚拟变量 dummies = pd.get_dummies(df[col], prefix=col) df = pd.concat([df, dummies], axis=1) feature_columns.extend(dummies.columns.tolist()) print(f"✅ {col}编码: {len(dummies.columns)}个虚拟变量") print(f"\n🎯 总共创建 {len(feature_columns)} 个特征") return df, feature_columns def perform_clustering(df, feature_columns): """执行聚类分析""" print("\n=== 聚类分析 ===") # 选择数值特征 numeric_features = [col for col in feature_columns if pd.api.types.is_numeric_dtype(df[col])] print(f"使用 {len(numeric_features)} 个数值特征:") for feature in numeric_features[:5]: # 只显示前5个 print(f" - {feature}") if len(numeric_features) > 5: print(f" - ... 还有 {len(numeric_features)-5} 个特征") if len(numeric_features) == 0: print("❌ 错误: 没有可用的数值特征") return df, None, 0 # 准备数据 X = df[numeric_features].copy() # 数据标准化 scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # 测试不同的K值 print("\n🔍 测试不同聚类数量:") best_k = 4 best_score = -1 for k in range(2, 6): kmeans = KMeans(n_clusters=k, random_state=42, n_init=10) labels = kmeans.fit_predict(X_scaled) score = silhouette_score(X_scaled, labels) print(f" K={k}: 轮廓系数 = {score:.3f}") if score > best_score: best_score = score best_k = k print(f"✅ 选择 K={best_k} (最佳轮廓系数: {best_score:.3f})") # 执行最终聚类 final_kmeans = KMeans(n_clusters=best_k, random_state=42, n_init=10) df['cluster'] = final_kmeans.fit_predict(X_scaled) return df, final_kmeans, best_score def analyze_clusters(df): """分析聚类结果""" print("\n=== 聚类结果分析 ===") cluster_summary = [] for cluster_id in sorted(df['cluster'].unique()): cluster_data = df[df['cluster'] == cluster_id] size = len(cluster_data) percentage = size / len(df) * 100 print(f"\n📊 集群 {cluster_id}: {size} 人 ({percentage:.1f}%)") # 分析关键特征 if '月薪' in df.columns: avg_salary = cluster_data['月薪'].mean() print(f" 💰 平均月薪: {avg_salary:.0f} 元") if '年龄' in df.columns: avg_age = cluster_data['年龄'].mean() print(f" 🎂 平均年龄: {avg_age:.1f} 岁") # 分析分类字段的主要值 categorical_cols = df.select_dtypes(include=['object']).columns for col in categorical_cols[:3]: # 只分析前3个分类字段 if col in df.columns: top_value = cluster_data[col].value_counts().index[0] top_count = cluster_data[col].value_counts().iloc[0] top_percent = top_count / size * 100 print(f" 📝 主要{col}: {top_value} ({top_percent:.1f}%)") cluster_summary.append({ 'cluster_id': cluster_id, 'size': size, 'percentage': percentage }) return cluster_summary def create_user_profiles(df): """创建用户画像""" print("\n=== 用户画像定义 ===") profile_names = {} for cluster_id in sorted(df['cluster'].unique()): cluster_data = df[df['cluster'] == cluster_id] # 基于特征定义画像名称 if '月薪' in df.columns: avg_salary = cluster_data['月薪'].mean() overall_avg = df['月薪'].mean() if avg_salary > overall_avg * 1.2: income_level = "高收入" elif avg_salary < overall_avg * 0.8: income_level = "低收入" else: income_level = "中等收入" else: income_level = "" # 基于规模定义 cluster_sizes = [len(df[df['cluster'] == cid]) for cid in df['cluster'].unique()] if len(cluster_data) == max(cluster_sizes): size_desc = "主流" elif len(cluster_data) == min(cluster_sizes): size_desc = "小众" else: size_desc = "细分" profile_name = f"{size_desc}{income_level}消费者" profile_names[cluster_id] = profile_name print(f" 集群 {cluster_id}: {profile_name}") df['user_profile'] = df['cluster'].map(profile_names) return df, profile_names def generate_report(df, feature_count, silhouette_score, profile_names): """生成分析报告""" print("\n=== 生成分析报告 ===") timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S') report = f""" 消费者行为聚类分析报告 ==================== 生成时间: {timestamp} 数据规模: {len(df)} 条记录 分析特征: {feature_count} 个 聚类质量: 轮廓系数 {silhouette_score:.3f} 用户群体分布 ------------ """ profile_counts = df['user_profile'].value_counts() for profile, count in profile_counts.items(): percentage = count / len(df) * 100 report += f"- {profile}: {count} 人 ({percentage:.1f}%)\n" report += f""" 各群体详细分析 -------------- """ for cluster_id in sorted(df['cluster'].unique()): cluster_data = df[df['cluster'] == cluster_id] profile_name = profile_names[cluster_id] report += f"\n【{profile_name}】\n" report += f"规模: {len(cluster_data)} 人\n" # 关键指标 if '月薪' in df.columns: avg_salary = cluster_data['月薪'].mean() report += f"- 平均月薪: {avg_salary:.0f} 元\n" if '年龄' in df.columns: avg_age = cluster_data['年龄'].mean() report += f"- 平均年龄: {avg_age:.1f} 岁\n" # 消费特征 categorical_fields = ['消费偏好', '消费领域', '购物动机'] for field in categorical_fields: if field in df.columns: top_value = cluster_data[field].mode()[0] if len(cluster_data[field].mode()) > 0 else "无数据" report += f"- 主要{field}: {top_value}\n" report += f""" 业务建议 -------- """ # 基于分析结果的简单建议 largest_group = df['user_profile'].value_counts().index[0] largest_size = df['user_profile'].value_counts().iloc[0] largest_percent = largest_size / len(df) * 100 report += f"1. **重点目标**: {largest_group} 占比最大 ({largest_percent:.1f}%),应作为核心目标群体\n" if '月薪' in df.columns: high_income_groups = [name for name in profile_names.values() if '高收入' in name] if high_income_groups: report += f"2. **高价值客户**: {', '.join(high_income_groups)} 具有较高消费能力\n" report += "3. **精准营销**: 根据不同群体特征制定个性化策略\n" report += "4. **产品优化**: 基于消费偏好调整产品和服务组合\n" return report def save_results(df, report): """保存分析结果""" print("\n=== 保存分析结果 ===") # 保存聚类结果 results_file = 'data/final/clustering_results.csv' df.to_csv(results_file, index=False, encoding='utf-8-sig') print(f"✅ 聚类结果: {results_file}") # 保存分析报告 report_file = 'results/analysis_report.txt' with open(report_file, 'w', encoding='utf-8') as f: f.write(report) print(f"✅ 分析报告: {report_file}") # 保存群体统计 stats_file = 'results/cluster_summary.csv' summary = df['user_profile'].value_counts().reset_index() summary.columns = ['user_profile', 'count'] summary['percentage'] = summary['count'] / len(df) * 100 summary.to_csv(stats_file, index=False, encoding='utf-8-sig') print(f"✅ 群体统计: {stats_file}") def main(): """主函数""" print("🎯 消费者行为聚类分析") print("=" * 50) # 1. 项目设置 setup_project() # 2. 检查环境 if not check_dependencies(): return # 3. 加载数据 df = load_data() if df is None: return # 4. 数据探索 df = explore_data(df) # 5. 特征工程 df, feature_columns = create_features(df) # 6. 聚类分析 df, kmeans_model, silhouette_score = perform_clustering(df, feature_columns) if kmeans_model is None: return # 7. 结果分析 cluster_summary = analyze_clusters(df) # 8. 用户画像 df, profile_names = create_user_profiles(df) # 9. 生成报告 report = generate_report(df, len(feature_columns), silhouette_score, profile_names) # 10. 保存结果 save_results(df, report) # 完成提示 print("\n🎉 分析完成!") print("=" * 50) print("📊 主要成果:") print(f" - 识别出 {len(profile_names)} 个消费者群体") print(f" - 最大群体: {df['user_profile'].value_counts().index[0]}") print(f" - 聚类质量: {silhouette_score:.3f}") print(f"\n📁 输出文件:") print(f" - data/final/clustering_results.csv") print(f" - results/analysis_report.txt") print(f" - results/cluster_summary.csv") if __name__ == "__main__": main() ``` ## 🚀 **运行项目** ### **直接运行(无需虚拟环境):** ```bash python src/consume.py ``` ### **如果遇到包缺失错误:** ```bash # 安装必要包 pip install pandas numpy scikit-learn # 然后重新运行 python src/consume.py ``` ## 📋 **项目特点** 1. ✅ **简单直接** - 使用本机环境,无需虚拟环境配置 2. ✅ **高质量数据处理** - 跳过预处理,专注分析 3. ✅ **自动特征工程** - 智能创建数值和分类特征 4. ✅ **智能聚类** - 自动选择最佳聚类数量 5. ✅ **详细分析报告** - 完整的业务洞察和建议 6. ✅ **结果持久化** - 所有输出自动保存 ## 💡 **使用提示** 1. **数据准备**: 确保 `consume1.csv` 文件在 `data/raw/` 目录中 2. **环境检查**: 代码会自动检查必要的Python包 3. **结果查看**: 分析完成后查看 `results/` 目录中的报告文件 4. **自定义调整**: 可以根据实际数据字段调整特征工程部分 帮我生成一下详细的步骤
最新发布
10-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值