简介:这是一份面向数据科学初学者与NLP实践者的葡萄酒评论分析数据集,适用于文本挖掘、情感分析、品类推荐系统建模及统计可视化等学习与项目开发场景。资源包含3个核心文件:2个CSV格式主数据集(分别含13万和15万条完整评论记录,涵盖品种、产区、酒庄、价格、评分及自由文本描述)与1个JSON格式子集(6919条结构化节点,便于快速验证解析逻辑),整体压缩包仅26.84MB,轻量易加载。目前已有101人下载学习,适合开展端到端数据分析实战——读者可直接调用Pandas清洗字段、用spaCy或NLTK处理评论文本、结合Seaborn绘制价格-评分分布热力图,并基于产地与品种构建基础推荐规则。数据字段丰富、样本规模适中、格式兼容性强,是入门级真实业务数据集的典型代表。
1. 项目概述:一份数据爱好者的宝藏
如果你对数据分析、机器学习或者葡萄酒文化感兴趣,手头却缺少一份高质量、体量足够大的数据集来练手或研究,那么今天聊的这个“葡萄酒评论数据集”绝对值得你花时间深入了解。这不是一份简单的商品列表,而是一个包含了超过13万条专业酒评、涵盖全球多个产区、跨越数十年时间的结构化数据宝藏。我最初接触到它,是为了做一个关于风味预测的小项目,结果发现它的深度和广度远超预期,完全能支撑起从入门到进阶的多种数据应用场景。
简单来说,这个数据集以三个CSV文件的形式存在,总计超过13万条记录。每一条记录都不仅仅是一瓶酒的名字和价格,而是一篇浓缩的专业品酒笔记,包含了品酒师对酒款外观、香气、口感和整体印象的详细描述,并附有产地、品种、评分等关键元数据。对于数据科学新手,它是练习数据清洗、探索性分析(EDA)和可视化的绝佳材料;对于有一定经验的分析师或算法工程师,它可以用来构建文本分析模型、推荐系统,甚至研究消费趋势与产区声誉之间的关系。无论你是想用pandas和matplotlib做一次酣畅淋漓的数据探索,还是想用scikit-learn或深度学习框架训练一个能“读懂”酒评的模型,这份数据都能提供坚实的基石。
2. 数据集深度解析与核心价值
2.1 数据来源与结构拆解
这份数据集的核心价值,首先体现在其数据来源的权威性和结构的丰富性上。它并非爬取自电商网站的用户短评,而是聚合了来自《葡萄酒观察家》(Wine Spectator)、《葡萄酒爱好者》(Wine Enthusiast)等国际权威葡萄酒刊物网站的专业酒评。这意味着每条记录背后的文本,都是由训练有素的品酒师按照相对标准化的流程撰写而成,在描述的专业性、用词的规范性以及评分的可信度上,都远高于普通用户评论。
数据集包含三个CSV文件,通常的命名和内容划分如下:
winemag-data_first150k.csv: 顾名思义,包含了前15万条记录。这是最常用作入门和主体分析的文件。winemag-data-130k-v2.csv: 一个包含了约13万条记录的版本,可能是某个时间点的快照或去重、清洗后的版本,常与第一个文件内容有大量重叠。winemag-data-130k-v2.csv(另一个同名或类似文件): 有时会出现,可能包含一些额外的字段或更新。
尽管文件数量和具体记录数可能有细微差别,但其核心字段结构是高度一致的。理解这些字段是挖掘数据价值的第一步。主要字段通常包括:
country: 葡萄酒生产国。这是进行地理区域分析的基础,比如比较法国波尔多与美国纳帕谷的平均评分。province: 产区所在的省或州。更细粒度的地理信息,用于深入分析特定产区的风格。region_1,region_2: 更具体的产区,例如村庄(如波亚克)、子产区等。region_2有时会更精细。winery: 酒庄名称。研究酒庄声誉和品质稳定性的关键。variety: 葡萄品种。如赤霞珠(Cabernet Sauvignon)、黑皮诺(Pinot Noir)、霞多丽(Chardonnay)等。是分析品种特性的核心维度。description:文本富矿。品酒师的完整品酒笔记,通常包含对香气(黑醋栗、雪松)、口感(单宁顺滑、酸度明亮)和余味的描述。这是自然语言处理(NLP)的绝佳素材。points: 评分,通常是百分制(如90分)。这是最直接的量化质量指标,用于监督学习中的回归或分类任务。price: 价格(通常以美元计)。研究价格与评分关系(性价比)、市场定位的基础。designation: 葡萄园名称。对于高端酒款,这个字段很重要。taster_name,taster_twitter_handle: 品酒师姓名及其社交媒体账号。可用于分析不同品酒师的评分偏好或风格。
注意:在实际使用中,你首先需要用
pandas加载数据并检查每个文件的字段完整性和唯一性。经常会有一些字段存在大量缺失值(如designation),在分析前需要评估是否保留或如何处理。
2.2 核心应用场景与研究方向
拥有这样一份结构化和非结构化信息并存的数据集,能玩出的花样非常多。我们可以从由浅入深几个层面来看它的应用场景:
2.2.1 入门级:数据清洗与探索性分析(EDA)实战对于刚接触数据分析的朋友,这个数据集提供了真实的、不“干净”的数据环境。你会遇到缺失值(如某些酒没有价格)、重复记录、文本中的特殊字符、国家名称不一致(如US和USA)等问题。解决这些问题的过程,就是学习pandas的fillna,drop_duplicates,str访问器等方法的最佳实践。之后,你可以进行一系列有趣的探索:
- 评分分布:全球葡萄酒的评分是否符合正态分布?高分段(>95)和低分段(<85)的酒占比多少?
- 价格与评分的关系:绘制价格-评分的散点图或计算相关系数。价格越贵,分数一定越高吗?是否存在“性价比之王”(高分低价)?
- 产区与品种分析:哪个国家生产的葡萄酒平均评分最高?哪种葡萄品种最受品酒师青睐?用
groupby和聚合函数就能轻松得出答案。 - 文本长度分析:描述字段的长度与评分有关系吗?是不是好酒会被描述得更详细?
2.2.2 进阶级:可视化与统计建模在EDA的基础上,可以引入更复杂的可视化(如seaborn,plotly)和统计检验。
- 地理可视化:利用
country和province字段,在地图上用颜色深浅或气泡大小展示不同产区的平均评分或产量,直观发现世界葡萄酒的“黄金地带”。 - 价格区间分析:将价格分段(如<$20, $20-$50, $50-$100, >$100),比较不同价格区间的评分分布、主要品种和产区,刻画市场结构。
- 假设检验:例如,“意大利葡萄酒的平均评分是否显著高于澳大利亚?”可以使用t检验来验证。或者探索不同品酒师(
taster_name)的评分标准是否存在系统性差异。
2.2.3 专业级:自然语言处理与机器学习这是数据集最能体现价值的地方,即将非结构化的文本描述转化为可量化的洞察或预测能力。
- 情感分析与风味提取:对
description字段进行情感分析,判断酒评是积极还是消极。更进一步,可以提取关键风味词(如“果味”、“橡木”、“单宁”、“酸度”),构建每款酒的“风味画像”。 - 评分预测模型:以
description文本为主要特征,points评分为目标变量,构建回归模型。你可以从简单的TF-IDF特征+线性回归开始,尝试到词嵌入(Word2Vec, FastText)+神经网络。这能检验机器“读懂”酒评并判断质量的能力。 - 酒款推荐系统:基于品种、产区、风味描述文本的相似度,为喜欢某款酒的用户推荐相似酒款。这需要用到文本相似度计算(如余弦相似度)或协同过滤算法。
- 价格预测:结合品种、产区、评分和描述文本,预测一款葡萄酒的市场价格。这是一个经典的回归问题。
3. 实操指南:从数据加载到深度探索
3.1 环境准备与数据加载
工欲善其事,必先利其器。我推荐使用Python的Jupyter Notebook或VS Code等交互式环境进行分析,主要依赖以下库:
pip install pandas numpy matplotlib seaborn plotly scikit-learn nltk首先,我们加载数据并对其进行初步审视。这里以最常见的winemag-data-130k-v2.csv为例。
import pandas as pd import numpy as np # 加载数据 df = pd.read_csv('winemag-data-130k-v2.csv') # 查看数据形状和基本信息 print(f"数据集形状: {df.shape}") # 输出例如 (129971, 14) print(df.info()) # 查看前几行数据,了解字段内容 print(df.head()) # 检查缺失值情况 print(df.isnull().sum().sort_values(ascending=False))运行这段代码,你会立刻对数据规模、字段类型和数据的“整洁度”有一个整体把握。通常会发现region_2,designation,taster_twitter_handle等字段缺失严重,而country,variety,description,points等核心字段完整性较好。
3.2 数据清洗与预处理实战
面对真实数据,清洗是必不可少且耗时的一步。以下是一些关键操作:
3.2.1 处理缺失值
- 关键字段缺失:对于
country或variety缺失的记录,如果数量不多(比如<1%),可以考虑直接删除,因为这两项是分析的基础维度。如果数量多,则需要根据其他信息(如酒庄、描述)进行推断,或标记为“Unknown”。 - 价格缺失:
price字段缺失很常见。不要简单地用均值或中位数填充,因为这可能严重扭曲分布。更好的策略是:在需要价格的分析中,暂时剔除这些记录;或者,建立一个预测模型,用其他特征(品种、产区、评分)来预测缺失的价格,但这本身就是一个子项目。 - 文本描述缺失:
description是核心,极少缺失。万一缺失,应直接删除该行。
# 示例:删除关键字段缺失的行 df_clean = df.dropna(subset=['country', 'variety', 'description', 'points']).copy() # 对于价格,我们可以先创建一个布尔标签,标记是否有价格 df_clean['has_price'] = df_clean['price'].notnull()3.2.2 文本描述字段的预处理如果后续要进行NLP分析,对description的预处理至关重要:
import re import nltk from nltk.corpus import stopwords # 可能需要先下载停用词资源 # nltk.download('stopwords') stop_words = set(stopwords.words('english')) def clean_text(text): # 转换为小写 text = text.lower() # 移除标点符号和数字(根据需求,有时数字如年份可能有用) text = re.sub(r'[^\w\s]', ' ', text) text = re.sub(r'\d+', ' ', text) # 移除多余空白字符 text = ' '.join(text.split()) # 移除停用词(可选,对于某些分析可能保留更好) # text = ' '.join([word for word in text.split() if word not in stop_words]) return text df_clean['description_clean'] = df_clean['description'].apply(clean_text)3.2.3 处理分类字段对于country,variety等分类变量,需要查看其唯一值数量,对于值特别多的(如成千上万个酒庄),在建模时可能需要考虑编码方式(如目标编码)或进行归类。
print(f"国家数量: {df_clean['country'].nunique()}") print(f"葡萄品种数量: {df_clean['variety'].nunique()}") # 查看品种分布,可能只关注前20大品种 top_varieties = df_clean['variety'].value_counts().head(20)3.3 基础探索性分析与可视化
清洗完成后,就可以开始有趣的探索了。这里展示几个核心分析方向:
3.3.1 评分与价格分析
import matplotlib.pyplot as plt import seaborn as sns plt.figure(figsize=(12, 5)) # 1. 评分分布 plt.subplot(1, 2, 1) sns.histplot(df_clean['points'], bins=20, kde=True) plt.title('葡萄酒评分分布') plt.xlabel('评分 (Points)') plt.ylabel('频数') # 2. 价格分布(取对数后更直观,因为价格长尾) plt.subplot(1, 2, 2) price_log = np.log1p(df_clean['price'].dropna()) # log(1+price) 处理0值 sns.histplot(price_log, bins=30, kde=True) plt.title('葡萄酒价格分布 (取对数)') plt.xlabel('log(1+Price)') plt.ylabel('频数') plt.tight_layout() plt.show() # 3. 评分 vs 价格散点图 plt.figure(figsize=(10, 6)) sns.scatterplot(data=df_clean.dropna(subset=['price']), x='price', y='points', alpha=0.4) plt.xscale('log') # 价格取对数坐标 plt.title('葡萄酒评分与价格关系 (价格取对数)') plt.xlabel('Price (USD, log scale)') plt.ylabel('Points') plt.show()3.3.2 产区与品种分析
# 计算各国平均评分和酒款数量 country_stats = df_clean.groupby('country').agg( avg_points=('points', 'mean'), count=('points', 'count') ).sort_values('avg_points', ascending=False).round(2) # 筛选出至少有100款酒的国家,避免小样本误差 country_stats_filtered = country_stats[country_stats['count'] >= 100] print(country_stats_filtered.head(10)) # 可视化 plt.figure(figsize=(14, 8)) top_countries = country_stats_filtered.head(15).index df_top = df_clean[df_clean['country'].isin(top_countries)] sns.boxplot(data=df_top, x='country', y='points', order=top_countries) plt.xticks(rotation=45) plt.title('主要产酒国评分箱线图 (至少100款样本)') plt.xlabel('Country') plt.ylabel('Points') plt.tight_layout() plt.show()4. 进阶应用:构建一个简单的评分预测模型
让我们尝试一个经典的NLP任务:仅根据酒评描述文字,预测其评分。这是一个回归问题。
4.1 特征工程与数据准备
我们将使用TF-IDF将文本描述转换为数值特征。
from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.model_selection import train_test_split from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score # 为了演示,我们使用一个子集以提高速度 df_sample = df_clean.sample(n=20000, random_state=42).copy() # 定义特征(X)和目标(y) X_text = df_sample['description_clean'] y = df_sample['points'] # 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X_text, y, test_size=0.2, random_state=42) # 使用TF-IDF向量化文本,限制最大特征数以控制维度 vectorizer = TfidfVectorizer(max_features=5000, stop_words='english', ngram_range=(1, 2)) X_train_tfidf = vectorizer.fit_transform(X_train) X_test_tfidf = vectorizer.transform(X_test) print(f"训练集特征维度: {X_train_tfidf.shape}") print(f"测试集特征维度: {X_test_tfidf.shape}")4.2 模型训练与评估
我们先从一个简单的线性回归开始,作为基线模型。
# 初始化并训练模型 lr_model = LinearRegression() lr_model.fit(X_train_tfidf, y_train) # 在测试集上进行预测 y_pred = lr_model.predict(X_test_tfidf) # 评估模型性能 mse = mean_squared_error(y_test, y_pred) mae = mean_absolute_error(y_test, y_pred) r2 = r2_score(y_test, y_pred) print(f"线性回归模型性能:") print(f" 均方误差 (MSE): {mse:.2f}") print(f" 平均绝对误差 (MAE): {mae:.2f}") print(f" 决定系数 (R²): {r2:.4f}") # 解读:MAE约为2.5,意味着模型预测的评分平均误差在2.5分左右。考虑到评分是80-100分的尺度,这个结果作为基线是可以接受的。4.3 模型优化思路与特征重要性
线性模型可能不足以捕捉复杂的文本-评分关系。我们可以尝试以下优化路径:
- 使用更复杂的模型:如随机森林回归(
RandomForestRegressor)、梯度提升树(如XGBRegressor)或简单的神经网络。这些模型能捕捉非线性关系。 - 改进文本特征:
- 使用词嵌入:用预训练的词向量(如GloVe, spaCy)代替TF-IDF,可以更好地捕捉语义信息。
- 使用深度学习模型直接处理文本:如LSTM、Transformer(BERT)等,进行端到端的训练。这需要更多的数据和计算资源,但潜力巨大。
- 融入结构化特征:将品种、国家等分类变量进行编码(如One-Hot Encoding),与文本的TF-IDF特征拼接在一起,构建混合特征模型。
即使使用简单的线性模型,我们也可以查看哪些词对高评分(正权重)或低评分(负权重)贡献最大。
# 获取特征名称和对应系数 feature_names = vectorizer.get_feature_names_out() coef = lr_model.coef_ # 创建(特征,系数)的元组列表并排序 coef_df = pd.DataFrame({'feature': feature_names, 'coef': coef}) top_positive = coef_df.sort_values('coef', ascending=False).head(10) top_negative = coef_df.sort_values('coef', ascending=True).head(10) print("与高评分最相关的词语:") print(top_positive[['feature', 'coef']]) print("\n与低评分最相关的词语:") print(top_negative[['feature', 'coef']])你可能会发现,“complexity”、“balance”、“length”、“finish”等描述酒体结构和余味的词与高分正相关,而“simple”、“thin”、“acidic”(在不恰当的语境下)可能与低分相关。这本身就是一个有趣的发现,揭示了专业品酒师的评价维度。
5. 常见问题与避坑指南
在实际使用这份数据集的过程中,我遇到过不少坑,这里总结一下,希望能帮你节省时间。
5.1 数据一致性与重复记录问题
- 问题:不同文件间(如
first150k和130k-v2)可能存在大量重复记录,直接合并会导致分析失真。 - 对策:在开始任何分析前,先基于唯一标识(如果存在如
id字段)或关键字段组合(如title、winery、variety、points)进行去重。使用pandas的drop_duplicates()方法。 - 实操心得:我通常会用
df.duplicated().sum()快速检查重复行数。对于没有明确ID的数据,我会选取几个关键字段进行去重,但会小心不要误删不同年份的同名酒款。有时,保留一个文件作为主数据集是最简单的选择。
5.2 价格数据的陷阱
- 问题:
price字段缺失率高,且分布极度右偏(少数天价酒拉高了整体范围)。 - 对策:
- 谨慎填充:不要用全局均值/中位数填充,考虑按品种-国家分组后的中位数填充,或直接标记缺失用于特定分析。
- 分析时取对数:在可视化或建模涉及价格时,对其取对数(
np.log1p(price))可以使分布更接近正态,减少极端值影响。 - 分箱处理:将价格划分为几个区间(如经济型、中端、高端、奢侈型),进行分组分析,比直接使用原始价格更稳健。
- 实操心得:我做过一个分析,发现直接计算价格与评分的相关系数很低,但取对数后,在特定价格区间内(比如$20-$100),正相关性变得明显。这说明关系是非线性的。
5.3 文本分析的挑战
- 问题:
description字段虽然质量高,但包含大量专业术语、形容词和比喻,标准NLP预处理(如移除停用词)可能会丢失关键信息(例如,“finish”这个词在酒评中极其重要,但在通用停用词列表中)。 - 对策:
- 自定义停用词表:基于领域知识,构建葡萄酒品鉴专用的停用词表和保留词表。
- n-gram特征:在TF-IDF中使用二元或三元词组(
ngram_range=(1,3)),可以捕捉“long finish”、“ripe fruit”这样的关键短语。 - 领域词嵌入:如果条件允许,使用在大量葡萄酒相关文本上训练的词向量,会比通用词向量(如Google News)表现更好。
- 实操心得:在构建预测模型初期,我保留了所有停用词,并使用了1-3 gram,发现模型性能比移除停用词只用1 gram时要好。后来我手动检查了高频词,将“wine”这种无意义的词加入停用词,而保留了“acidity”、“tannin”等专业词。
5.4 类别不平衡与样本选择
- 问题:数据集中,某些国家(如美国、法国)或品种(如赤霞珠、霞多丽)的样本量极大,而一些小众产区或品种样本很少。这可能导致分析结果向主流倾斜,模型难以预测小众产品。
- 对策:
- 分层抽样:在建模时,确保训练集和测试集中各类别的比例与总体一致。
- 设置样本量阈值:在比较国家或品种时,只考虑样本量超过某个阈值(如50或100)的类别,以保证统计显著性。
- 重采样技术:对于分类问题,如果目标变量是分类(如将评分分为“优秀”、“良好”、“一般”),可以使用过采样或欠采样技术处理类别不平衡。
- 实操心得:当我做国家间平均评分排名时,最初的结果包含了一些只有一两款酒的国家,排名很高但毫无意义。加上最小样本量限制后,结果才变得可靠。
这份“葡萄酒评论数据集”就像一座富矿,表层是清晰的结构化数据,深层则蕴藏在丰富的文本描述之中。从最初的数据清洗到构建一个能初步理解酒评的模型,整个过程充满了挑战和乐趣。它教会我的不仅是pandas或scikit-learn的用法,更是如何处理真实、混乱但有价值的数据的思维方式。如果你正在寻找一个能贯穿数据分析全流程的练手项目,不妨从加载这三个CSV文件开始,亲自挖一挖这座矿,相信你会有自己的发现。
本文还有配套的精品资源,点击获取