
简介这是一份面向数据科学初学者与NLP实践者的葡萄酒评论分析数据集适用于文本挖掘、情感分析、品类推荐系统建模及统计可视化等学习与项目场景。资源包含3个核心文件2个CSV格式主数据表分别含13万与15万条完整评论记录涵盖品种、产区、酒庄、价格、评分及自由文本描述和1个JSON格式精简样本6919条便于快速验证与调试压缩包大小为26.84MB结构简洁开箱即用。目前已有101人学习下载反映出其在入门级实战数据集中的实用热度。读者可直接加载CSV开展探索性数据分析EDA、构建葡萄酒描述的TF-IDF或词向量模型、训练价格预测回归模型或基于文本生成产地/品种分类器JSON文件则适合作为API接口模拟或轻量级测试基准整体兼顾规模性、字段丰富性与工程友好性。1. 项目缘起一份被低估的葡萄酒数据宝藏如果你对数据分析、机器学习或者仅仅是葡萄酒文化感兴趣那么“葡萄酒评论数据集”这个名字可能已经在你眼前闪过很多次了。这个在Kaggle等数据科学社区流传甚广的数据集以其超过13万条记录的庞大体量和丰富的文本信息成为了许多数据爱好者的练手首选。但说实话大多数人对它的使用可能还停留在“导入pandas看看描述性统计做个词云”的初级阶段。这就像得到了一瓶年份不错的葡萄酒却只用来做了烹饪料酒实在是有些可惜。我最初接触这个数据集是为了一个简单的文本情感分析项目。但随着挖掘的深入我发现这130k条记录背后远不止是“好喝”或“不好喝”的二元判断。它是一张由全球品酒师、消费者共同编织的、关于风味、产地、价格与个人体验的复杂网络。三个CSV文件通常指winemag-data_first150k.csvwinemag-data-130k-v2.csv以及可能衍生的清洗后版本看似简单却包含了countryprovincevariety葡萄品种points评分price 以及最核心的description品酒笔记等关键字段。这些字段的交叉分析能揭示出许多反直觉的行业洞察比如“哪些产区的赤霞珠性价比最高”、“‘矿物感’这种描述通常伴随着高价格吗”、“消费者描述和专家描述在关注点上有何不同”这份数据集的价值在于它提供了一个从数据角度理解一个古老而感性行业的绝佳切口。它适合数据分析初学者作为第一个有深度的实战项目也适合中级从业者练习特征工程、自然语言处理NLP和可视化甚至能为市场研究者、葡萄酒爱好者提供直观的决策参考。接下来我将抛开常规的数据概览带你深入这份数据集的肌理看看如何把它“榨”出更多汁液。2. 数据初探与质量清洗避开第一个大坑拿到数据的第一步绝不是急着跑模型。很多教程会跳过这步直接展示漂亮的结果但这恰恰是项目能否复现、结论是否可靠的基础。这个数据集虽然知名但也藏着不少“坑”。2.1 文件解析与核心字段理解通常我们主要使用winemag-data-130k-v2.csv这个文件它包含了截至2017年的约13万条记录。用pandas加载后我们首先关注的不是行数而是字段的真实含义和质量。import pandas as pd # 加载数据 df pd.read_csv(winemag-data-130k-v2.csv) print(df.shape) print(df.columns.tolist())关键字段解读points: 葡萄酒评分范围通常在80-100分之间。这是我们的核心目标变量之一用于回归或分类如将90分定义为“优质酒”。price: 价格美元。注意存在大量NaN值这是后续处理的重点。countryprovinceregion_1region_2: 地理信息层级。country和province相对完整region信息缺失较多且命名不规范如大小写、拼写变体。variety: 葡萄品种。这是分析风味差异的黄金维度但同样存在同义词问题如“Pinot Noir” vs. “Pinot noir”。winery: 酒庄。可用于品牌效应分析。description: 品酒笔记文本。这是NLP的富矿包含了风味、口感、香气等主观描述。designation: 葡萄园名称。信息缺失严重。taster_nametaster_twitter_handle: 评论者信息。可用于分析不同评论者的评分偏好。2.2 系统性数据清洗实战清洗不是简单dropna()而是有策略的。缺失值处理策略价格缺失直接删除所有价格缺失的记录是最粗暴的做法可能会引入偏差也许某些特定产区的酒就是不标价。一个更稳妥的方法是分维度进行估算或标注。例如可以按country和variety分组用该组的中位数价格进行填充并新增一个布尔列price_imputed来标记哪些价格是估算的便于后续分析时区分。# 分组中位数填充价格并标记 df[price_imputed] df[price].isna() df[price] df.groupby([country, variety])[price].transform(lambda x: x.fillna(x.median())) # 如果分组后仍有缺失用全局中位数填充 df[price] df[price].fillna(df[price].median())国家/省份缺失对于有region_1但国家缺失的记录可以尝试通过外部知识库如一个产区-国家映射表进行补全但工作量较大。对于小批量缺失可以考虑删除。品种缺失如果variety缺失这条记录对于基于品种的分析价值大减通常可以考虑删除。文本字段规范化varietycountry等字段的文本清洗至关重要。# 品种名称规范化示例 df[variety_clean] df[variety].str.lower().str.strip() # 处理常见变体这需要一些领域知识 variety_mapping { pinot noir: pinot noir, pinot noir.: pinot noir, cabernet sauvignon: cabernet sauvignon, cabernet sauvignon.: cabernet sauvignon, # ... 其他映射 } df[variety_clean] df[variety_clean].replace(variety_mapping)异常值与逻辑检查价格异常检查是否有价格为0或极高如10000美元的记录需核实是否为录入错误。分数逻辑检查points是否在合理区间如80-100。偶尔会出现0分或超百分需处理。文本长度检查description字段是否有空字符串或极短的无效评论。实操心得不要追求一次性清洗“完美”。采用迭代式清洗先处理影响核心分析的缺失值如价格跑一遍基础分析再根据分析需要回头处理更细致的文本规范化或次级字段缺失。这样效率更高。另外务必保存清洗前后的数据版本并记录下每一步清洗操作的逻辑这是可复现性的关键。3. 分析视角一价格与分数的关系性价比真的存在吗“一分钱一分货”在葡萄酒世界成立吗这是最直观的问题。我们可以从几个维度切入。3.1 整体趋势与“价格分数比”简单的散点图pricevspoints会显示正相关但非常分散。计算价格分数比Price-Point Ratio PPR更有趣PPR price / points。这个值越低意味着“每分花费”越少理论上性价比越高。但要注意分数是80-100的尺度这个比值对低价酒可能不敏感。更实用的方法是分区间分析# 将价格分段 df[price_bin] pd.cut(df[price], bins[0, 20, 50, 100, 200, 500, df[price].max()], labels[20, 20-50, 50-100, 100-200, 200-500, 500]) # 计算每个价格区间的平均分和中位数价格 price_summary df.groupby(price_bin).agg({points: mean, price: median, variety: count}).round(2) price_summary.columns [avg_points, median_price, count] print(price_summary)你会发现从20美元到50-100美元区间平均分上升明显但超过200美元后平均分的提升曲线变得极其平缓。这就是葡萄酒世界的“边际效用递减”支付数倍的价格可能只为换取一两分的提升而这提升是否感知得到因人而异。3.2 按国家与品种的交叉性价比分析整体分析会掩盖细节。真正的宝藏藏在分组里。1. 寻找“性价比产区”按country和price_bin分组计算该分组内的平均分。然后在同一个价格区间内比如20-50美元对比不同国家的平均分。你可能会发现在这个价位段智利、阿根廷、葡萄牙的平均分常常高于法国、意大利的传统产区。这就是数据揭示的“性价比高地”。2. 品种的“价格天花板”分析对于同一个品种比如黑皮诺Pinot Noir画出不同国家产区的价格-分数散点图。你可能会看到勃艮第法国的黑皮诺聚集在高价区50美元分数也高而新西兰、美国的黑皮诺分布更广在中低价位20-50美元也有不少高分选手。这说明了不同产地对同一品种的“品牌溢价”或“风土溢价”。3. 构建自己的“寻酒地图”我们可以创建一个交互式表格或静态热力图核心指标是“同价位段内的分数排名”。例如筛选所有价格在15-25美元之间的酒然后按国家、品种聚合计算平均分并排序。这个结果对你下次买酒就有直接参考价值。踩坑记录早期我直接用price和points算相关系数结果很低就草率得出结论“价格与质量无关”。这是错误的因为关系是非线性的且受品种、产区干扰极大。必须进行分层、分组控制变量后关系才清晰显现。数据分析中看见“没有相关”时第一反应应该是“我是否混入了不同质的数据群”。4. 分析视角二品酒笔记文本挖掘——风味的数字密码description字段是这座金矿中最璀璨的部分。通过文本分析我们可以把主观的品尝感受转化为客观的数据特征。4.1 关键词提取与风味轮廓首先我们可以用TF-IDF或简单的词频统计找出整个数据集中最常出现的风味描述词。from sklearn.feature_extraction.text import TfidfVectorizer import nltk from nltk.corpus import stopwords # 下载停用词如果尚未下载 nltk.download(stopwords) stop_words set(stopwords.words(english)) # 添加葡萄酒描述中的常见非风味停用词 custom_stop stop_words.union([wine, flavors, aromas, finish, palate, drink, notes]) # 初始化TF-IDF限制最大特征数并过滤停用词 tfidf TfidfVectorizer(max_features100, stop_wordscustom_stop, ngram_range(1, 2)) tfidf_matrix tfidf.fit_transform(df[description].dropna()) feature_names tfidf.get_feature_names_out() # 查看最重要的词 dense tfidf_matrix.sum(axis0).A1 importance list(zip(feature_names, dense)) importance_sorted sorted(importance, keylambda x: x[1], reverseTrue) print(importance_sorted[:20])你会得到像‘black cherry’ ‘vanilla’ ‘oak’ ‘tannins’ ‘acidity’ ‘ripe fruit’ ‘red berries’ ‘spice’这样的高频词。这些词构成了数据集中葡萄酒的“基础风味词典”。4.2 情感分析描述的情绪与分数关联品酒笔记的情绪是积极还是消极我们可以使用预训练的情感分析模型如TextBlob VADER为每条描述打一个情感极性分数-1到1。from textblob import TextBlob def get_sentiment(text): if isinstance(text, str): return TextBlob(text).sentiment.polarity else: return 0 df[sentiment] df[description].apply(get_sentiment)接着分析sentiment分数与points的相关性。通常呈现强正相关这验证了常识好评语通常对应高分。但更有趣的是异常点分析找出那些情感分数高但评分低或情感分数低但评分高的酒。前者可能是评论者喜欢其风格但认为有技术缺陷后者可能是一款“严肃”的好酒描述客观冷静。4.3 主题模型LDA发现隐藏主题我们可以使用无监督的LDA主题模型来发现描述中隐藏的“话题簇”。from sklearn.decomposition import LatentDirichletAllocation from sklearn.feature_extraction.text import CountVectorizer # 先用CountVectorizer vectorizer CountVectorizer(max_df0.95, min_df2, stop_wordscustom_stop) dtm vectorizer.fit_transform(df[description].dropna()) # 训练LDA模型假设我们寻找10个主题 lda LatentDirichletAllocation(n_components10, random_state42) lda.fit(dtm) # 查看每个主题的关键词 def print_topics(model, feature_names, n_top_words): for topic_idx, topic in enumerate(model.components_): message fTopic #{topic_idx}: message .join([feature_names[i] for i in topic.argsort()[:-n_top_words - 1:-1]]) print(message) print_topics(lda, vectorizer.get_feature_names_out(), 10)你可能会得到诸如“橡木与香料”oak vanilla spice toast、“红色水果与单宁”cherry tannins red berry、“柑橘与矿物感”citrus mineral acidity lime、“陈年与复杂感”age complex earthy leather等主题。然后我们可以为每篇描述分配一个主主题再分析不同主题与产区、品种、价格的关系。例如“橡木与香料”主题可能更多与高价格、美国加州赤霞珠关联而“柑橘与矿物感”则可能与法国夏布利Chablis白葡萄酒关联。NLP实操陷阱直接对原始描述做词频统计会充斥“wine”“flavor”“finish”这类无区分度的词必须使用定制化的停用词表。另外LDA模型的结果解释需要一定的领域知识且主题数n_components需要多次调整尝试结合困惑度perplexity或一致性coherence分数来选择。5. 分析视角三评论者偏见与市场洞察数据集中包含了taster_name这让我们有机会分析不同评论者的“手松”或“手紧”程度以及他们的口味偏好。5.1 评论者评分风格分析首先统计每位评论者评分的分布均值、标准差、中位数。taster_stats df.groupby(taster_name)[points].agg([count, mean, std, median]).round(2) taster_stats taster_stats.sort_values(count, ascendingFalse) print(taster_stats.head(10))你会发现有些评论者的平均分系统性高于其他人。这不一定代表不公正可能源于他们评测的酒款范围不同专精高端酒 vs. 覆盖全价位。更科学的做法是控制价格和品种后看评论者的效应。例如只选取20-30美元的黑皮诺再看不同评论者打分的差异。这能更纯粹地反映其评分尺度。5.2 评论者口味偏好网络我们可以构建一个“评论者-品种”矩阵计算每位评论者对每个品种的平均分然后使用聚类分析如K-Means将评论者分组。结果可能会显示有些评论者明显偏爱酒体饱满的品种如赤霞珠、西拉给出的分数普遍较高而另一组评论者可能更欣赏优雅细腻的品种如黑皮诺、内比奥罗对前者打分相对保守。更进一步可以分析特定评论者的高频描述词与整体词频对比绘制其“个人风味雷达图”。这对于葡萄酒爱好者来说是找到与自己口味相近的评论者的好方法能提高选酒效率。5.3 时间趋势分析如果数据有时间戳原始数据集可能没有明确的评论日期但如果有版本包含时间信息我们可以做很多有趣的分析品种流行度变迁哪些品种的评论数量随时间增长最快可能是马尔贝克、阿尔巴利诺等价格通胀分析同一产区、同品种的酒扣除评分影响后价格随时间的变化趋势如何风味描述演变像“自然酒”、“橙酒”这类新兴概念相关的词汇是否在后期评论中出现频率陡增6. 从分析到应用构建一个简单的葡萄酒推荐原型将以上分析整合我们可以构思一个简单的、基于内容的葡萄酒推荐系统原型。思路是找到与你喜欢的酒款在关键维度上相似的其它酒款。步骤定义特征选取核心特征如variety_clean品种country国家price_bin价格区间以及从description中提取的top_flavor通过TF-IDF提取的前3个关键词和sentiment情感分数。特征向量化将分类变量品种、国家进行独热编码One-Hot Encoding数值变量价格区间、情感分数标准化文本关键词可以转化为词袋模型。计算相似度假设用户喜欢一款酒记录A。我们计算记录A与数据集中所有其他酒款在特征空间上的余弦相似度。生成推荐返回相似度最高的N款酒并排除记录A本身。同时可以给出推荐理由“这款酒与您喜欢的酒同属智利赤霞珠价格区间相同且描述中都强调了‘黑醋栗’和‘巧克力’的风味。”这个原型非常基础没有考虑用户历史行为协同过滤但它的优势是可解释性强。每一条推荐都能追溯到具体的特征匹配上让用户感觉更可信。项目进阶思考这个数据集还能怎么玩你可以尝试1)价格预测模型使用品种、国家、描述文本等特征预测葡萄酒的价格看模型能否捕捉那些无形的“品牌溢价”。2)虚假评论检测结合评分、描述情感、评论者历史行为构建模型识别可能异常的评价。3)风味搭配知识图谱从描述中提取“A与B”形式的风味共现词对如“黑莓与香草”构建一个风味关联网络探索哪些风味描述经常结伴出现。这份葡萄酒评论数据集就像一片等待深耕的葡萄园。大多数人只在表面采摘但只要你愿意向下挖掘进行细致的清洗、多维的切片、深度的文本挖掘你就能酿出属于自己的、见解独到的“数据美酒”。真正的收获不在于做出一个多么复杂的模型而在于通过数据理解一个复杂行业内在的逻辑与美感。最后在处理任何数据集时保持对数据来源和潜在偏差的警惕例如该数据集主要反映英语酒评媒体的观点让你的结论更加严谨。本文还有配套的精品资源点击获取