偏度去无踪:数据科学家的转换技巧
machinelearningmastery.com/skewness-be-gone-transformative-tricks-for-data-scientists/
数据转换使数据科学家能够将原始数据精炼、标准化,以适合分析的格式。这些转换不仅仅是程序步骤;它们对于减少偏差、处理偏斜分布和增强统计模型的稳健性至关重要。本章将主要关注如何解决偏斜数据。通过关注 Ames 住房数据集中的“SalePrice”和“YearBuilt”属性,你将看到正偏和负偏数据的示例,以及使用转换来规范其分布的方法。
让我们开始吧。
偏度去无踪:数据科学家的转换技巧
照片由 Suzanne D. Williams 拍摄。保留一些权利。
概述
本文分为五部分,它们是:
-
理解偏度及其转化的必要性
-
驯化正偏度的策略
-
驯化负偏度的策略
-
转换的统计评估
-
选择正确的转换
理解偏度及其转化的必要性
偏度是一个统计度量,描述数据分布围绕其均值的非对称性。简单来说,它指示数据的大部分是否集中在量表的一侧,另一侧则延伸出长尾。在数据分析中,你会遇到两种类型的偏度:
-
正偏度:当分布的尾部向较高值方向延伸,位于峰值的右侧时,就会发生正偏度。大多数数据点集中在量表的较低端,这表明虽然大多数值相对较低,但也有一些异常高的值。Ames 数据集中的‘SalePrice’属性展示了正偏度,因为大多数房屋的销售价格较低,但有少数房屋的销售价格显著较高。
-
负偏度:相反,负偏度发生在分布的尾部向较低值方向延伸,位于峰值的左侧。在这种情况下,数据集中在量表的较高端,较少的值向较低的数字延伸。Ames 数据集中的‘YearBuilt’特征是负偏度的一个完美示例,这表明尽管大多数房屋是在较近的年份建造的,但少部分房屋可以追溯到较早的时期。
为了更好地理解这些概念,让我们可视化偏度。
# Import the necessary libraries
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
from scipy.stats import boxcox, yeojohnson
from sklearn.preprocessing import QuantileTransformer
# Load the dataset
Ames = pd.read_csv('Ames.csv')
# Calculate skewness
sale_price_skew = Ames['SalePrice'].skew()
year_built_skew = Ames['YearBuilt'].skew()
# Set the style of seaborn
sns.set(style='whitegrid')
# Create a figure for 2 subplots (1 row, 2 columns)
fig, ax = plt.subplots(1, 2, figsize=(14, 6))
# Plot for SalePrice (positively skewed)
sns.histplot(Ames['SalePrice'], kde=True, ax=ax[0], color='skyblue')
ax[0].set_title('Distribution of SalePrice (Positive Skew)', fontsize=16)
ax[0].set_xlabel('SalePrice')
ax[0].set_ylabel('Frequency')
# Annotate Skewness
ax[0].text(0.5, 0.5, f'Skew: {sale_price_skew:.2f}', transform=ax[0].transAxes,
horizontalalignment='right', color='black', weight='bold',
fontsize=14)
# Plot for YearBuilt (negatively skewed)
sns.histplot(Ames['YearBuilt'], kde=True, ax=ax[1], color='salmon')
ax[1].set_title('Distribution of YearBuilt (Negative Skew)', fontsize=16)
ax[1].set_xlabel('YearBuilt')
ax[1].set_ylabel('Frequency')
# Annotate Skewness
ax[1].text(0.5, 0.5, f'Skew: {year_built_skew:.2f}', transform=ax[1].transAxes,
horizontalalignment='right', color='black', weight='bold',
fontsize=14)
plt.tight_layout()
plt.show()
对于‘SalePrice’,图表显示了明显的右偏分布,突显了数据分析中偏态的挑战。这种分布会使预测建模变得复杂,并掩盖见解,使得得出准确结论变得困难。相比之下,‘YearBuilt’表现出负偏态,其中分布显示较新的房屋占主导地位,而旧房屋则形成了向左延伸的长尾。
通过数据变换来处理偏态不仅仅是统计调整;这是揭示精确、可操作见解的关键步骤。通过应用变换,你旨在减轻偏态的影响,促进更可靠和可解释的分析。这一规范化过程提升了你进行有意义数据科学的能力,不仅仅是满足统计要求。它强调了你改善数据清晰度和实用性的承诺,为你在随后的数据变换探索中提供了有洞察力和影响力的发现的基础。
启动你的项目,请参考我的书籍 初学者的数据科学指南。它提供了自学教程和有效的代码。
驯服正偏态的策略
为了应对正偏态,你可以使用五种关键的变换方法:对数变换、平方根变换、Box-Cox 变换、Yeo-Johnson 变换和分位数变换。每种方法旨在减轻偏态,提高数据适合进一步分析的程度。
对数变换
这种方法特别适合右偏的数据,通过对所有数据点取自然对数来有效地最小化大规模的差异。数据范围的压缩使其更适合进一步的统计分析。
# Applying Log Transformation
Ames['Log_SalePrice'] = np.log(Ames['SalePrice'])
print(f"Skewness after Log Transformation: {Ames['Log_SalePrice'].skew():.5f}")
你可以看到偏态被减少了:
Skewness after Log Transformation: 0.04172
平方根变换
比对数变换更为温和,适用于中度偏态的数据。通过对每个数据点应用平方根,它减少了偏态并减小了异常值的影响,使分布更为对称。
# Applying Square Root Transformation
Ames['Sqrt_SalePrice'] = np.sqrt(Ames['SalePrice'])
print(f"Skewness after Square Root Transformation: {Ames['Sqrt_SalePrice'].skew():.5f}")
这会打印:
Skewness after Square Root Transformation: 0.90148
Box-Cox 变换
通过优化变换参数 lambda (λ) 提供灵活性,仅适用于正数据。Box-Cox 方法系统地寻找最佳的幂变换,以减少偏态并稳定方差,增强数据的正态性。
# Applying Box-Cox Transformation after checking all values are positive
if (Ames['SalePrice'] > 0).all():
Ames['BoxCox_SalePrice'], _ = boxcox(Ames['SalePrice'])
else:
# Consider alternative transformations or handling strategies
print("Not all SalePrice values are positive. Consider using Yeo-Johnson or handling negative values.")
print(f"Skewness after Box-Cox Transformation: {Ames['BoxCox_SalePrice'].skew():.5f}")
这是目前最好的变换,因为偏态非常接近于零:
Skewness after Box-Cox Transformation: -0.00436
Yeo-Johnson 变换
上述变换仅适用于正数据。Yeo-Johnson 变换类似于 Box-Cox,但适应于正数据和非正数据。它通过最佳变换参数修改数据。这种适应性使其能够管理更广泛的数据值范围内的偏态,提高其对统计模型的适用性。
# Applying Yeo-Johnson Transformation
Ames['YeoJohnson_SalePrice'], _ = yeojohnson(Ames['SalePrice'])
print(f"Skewness after Yeo-Johnson Transformation: {Ames['YeoJohnson_SalePrice'].skew():.5f}")
类似于 Box-Cox,变换后的偏态非常接近于零:
Skewness after Yeo-Johnson Transformation: -0.00437
分位数变换
分位数变换将数据映射到指定的分布,例如正态分布,通过将数据点均匀分布在所选分布中,有效地解决了偏态问题。这种变换规范化了数据的形状,专注于使分布更均匀或类似高斯分布,但由于其非线性特性和将数据恢复到原始形式的挑战,并不直接对线性模型有利。
# Applying Quantile Transformation to follow a normal distribution
quantile_transformer = QuantileTransformer(output_distribution='normal', random_state=0)
Ames['Quantile_SalePrice'] = quantile_transformer.fit_transform(Ames['SalePrice'].values.reshape(-1, 1)).flatten()
print(f"Skewness after Quantile Transformation: {Ames['Quantile_SalePrice'].skew():.5f}")
由于这种变换通过强力调整数据以适应高斯分布,偏态接近于零:
Skewness after Quantile Transformation: 0.00286
为了说明这些变换的效果,让我们看看在应用每种方法之前和之后的 ‘SalePrice’ 分布的视觉表现。
# Plotting the distributions
fig, axes = plt.subplots(2, 3, figsize=(18, 15)) # Adjusted for an additional plot
# Flatten the axes array for easier indexing
axes = axes.flatten()
# Hide unused subplot axes
for ax in axes[6:]:
ax.axis('off')
# Original SalePrice Distribution
sns.histplot(Ames['SalePrice'], kde=True, bins=30, color='skyblue', ax=axes[0])
axes[0].set_title('Original SalePrice Distribution (Skew: 1.76)')
axes[0].set_xlabel('SalePrice')
axes[0].set_ylabel('Frequency')
# Log Transformed SalePrice
sns.histplot(Ames['Log_SalePrice'], kde=True, bins=30, color='blue', ax=axes[1])
axes[1].set_title('Log Transformed SalePrice (Skew: 0.04172)')
axes[1].set_xlabel('Log of SalePrice')
axes[1].set_ylabel('Frequency')
# Square Root Transformed SalePrice
sns.histplot(Ames['Sqrt_SalePrice'], kde=True, bins=30, color='orange', ax=axes[2])
axes[2].set_title('Square Root Transformed SalePrice (Skew: 0.90148)')
axes[2].set_xlabel('Square Root of SalePrice')
axes[2].set_ylabel('Frequency')
# Box-Cox Transformed SalePrice
sns.histplot(Ames['BoxCox_SalePrice'], kde=True, bins=30, color='red', ax=axes[3])
axes[3].set_title('Box-Cox Transformed SalePrice (Skew: -0.00436)')
axes[3].set_xlabel('Box-Cox of SalePrice')
axes[3].set_ylabel('Frequency')
# Yeo-Johnson Transformed SalePrice
sns.histplot(Ames['YeoJohnson_SalePrice'], kde=True, bins=30, color='purple', ax=axes[4])
axes[4].set_title('Yeo-Johnson Transformed SalePrice (Skew: -0.00437)')
axes[4].set_xlabel('Yeo-Johnson of SalePrice')
axes[4].set_ylabel('Frequency')
# Quantile Transformed SalePrice (Normal Distribution)
sns.histplot(Ames['Quantile_SalePrice'], kde=True, bins=30, color='green', ax=axes[5])
axes[5].set_title('Quantile Transformed SalePrice (Normal Distn, Skew: 0.00286)')
axes[5].set_xlabel('Quantile Transformed SalePrice')
axes[5].set_ylabel('Frequency')
plt.tight_layout(pad=4.0)
plt.show()
以下视觉图提供了一个并排比较,帮助你更好地理解每种变换对房价分布的影响。
变换后的数据分布
这个视觉图清晰地展示了每种变换方法如何改变 ‘SalePrice’ 的分布,展示了实现更正态分布的效果。
驯服负偏态的策略
为了应对负偏态,你可以使用五种关键的变换方法:平方、立方、Box-Cox、Yeo-Johnson 和分位数变换。每种方法都旨在减轻偏态,提高数据的进一步分析适用性。
平方变换
这涉及对数据集中每个数据点进行平方(即,将其提高到 2 的幂)。平方变换有助于减少负偏态,因为它往往比高值扩展低值更多。然而,当所有数据点都是正值且负偏态程度不极端时,它更有效。
# Applying Squared Transformation
Ames['Squared_YearBuilt'] = Ames['YearBuilt'] ** 2
print(f"Skewness after Squared Transformation: {Ames['Squared_YearBuilt'].skew():.5f}")
它打印:
Skewness after Squared Transformation: -0.57207
立方变换
类似于平方变换,但涉及将每个数据点提高到 3 的幂。立方变换可以进一步减少负偏态,特别是在平方变换不足的情况下。它在扩展值方面更为激进,这对负偏态更严重的分布可能更有利。
# Applying Cubed Transformation
Ames['Cubed_YearBuilt'] = Ames['YearBuilt'] ** 3
print(f"Skewness after Cubed Transformation: {Ames['Cubed_YearBuilt'].skew():.5f}")
它打印:
Skewness after Cubed Transformation: -0.54539
Box-Cox 变换
一种更复杂的方法,通过找到最佳的 lambda (λ) 参数,将数据转换为正态分布。该变换仅适用于正值数据。Box-Cox 变换对多种分布非常有效,包括那些有负偏态的分布,通过使数据更对称来改进效果。对于负偏态数据,通常会找到一个正的 lambda,从而应用一种有效减少偏态的变换。
# Applying Box-Cox Transformation after checking all values are positive
if (Ames['YearBuilt'] > 0).all():
Ames['BoxCox_YearBuilt'], _ = boxcox(Ames['YearBuilt'])
else:
# Consider alternative transformations or handling strategies
print("Not all YearBuilt values are positive. Consider using Yeo-Johnson or handling negative values.")
print(f"Skewness after Box-Cox Transformation: {Ames['BoxCox_YearBuilt'].skew():.5f}")
你可以看到偏态比之前更接近于零:
Skewness after Box-Cox Transformation: -0.12435
Yeo-Johnson 变换
与 Box-Cox 变换类似,但 Yeo-Johnson 变换旨在处理正负数据。对于负偏斜的数据,Yeo-Johnson 变换可以即使在存在负值的情况下也能对分布进行标准化。它以减少偏斜度的方式调整数据,使其对包含正负值的数据集特别适用。
# Applying Yeo-Johnson Transformation
Ames['YeoJohnson_YearBuilt'], _ = yeojohnson(Ames['YearBuilt'])
print(f"Skewness after Yeo-Johnson Transformation: {Ames['YeoJohnson_YearBuilt'].skew():.5f}")
类似于 Box-Cox,你可以看到偏斜度接近零:
Skewness after Yeo-Johnson Transformation: -0.12435
分位数变换
这种方法将特征转换为符合指定分布,如正态分布,基于其分位数。它不对输入数据假设任何特定的分布形状。应用于负偏斜数据时,分位数变换可以有效地标准化分布。它特别适用于处理异常值,并使数据的分布变得均匀或正态,无论原始的偏斜度如何。
# Applying Quantile Transformation to follow a normal distribution
quantile_transformer = QuantileTransformer(output_distribution='normal', random_state=0)
Ames['Quantile_YearBuilt'] = quantile_transformer.fit_transform(Ames['YearBuilt'].values.reshape(-1, 1)).flatten()
print(f"Skewness after Quantile Transformation: {Ames['Quantile_YearBuilt'].skew():.5f}")
正如你之前在正偏斜的情况下看到的,分位数变换提供了最佳结果,因为最终的偏斜度最接近零:
Skewness after Quantile Transformation: 0.02713
为了说明这些变换的效果,让我们看一下“YearBuilt”分布在应用每种方法前后的可视化表示。
# Plotting the distributions
fig, axes = plt.subplots(2, 3, figsize=(18, 15))
# Flatten the axes array for easier indexing
axes = axes.flatten()
# Original YearBuilt Distribution
sns.histplot(Ames['YearBuilt'], kde=True, bins=30, color='skyblue', ax=axes[0])
axes[0].set_title(f'Original YearBuilt Distribution (Skew: {Ames["YearBuilt"].skew():.5f})')
axes[0].set_xlabel('YearBuilt')
axes[0].set_ylabel('Frequency')
# Squared YearBuilt
sns.histplot(Ames['Squared_YearBuilt'], kde=True, bins=30, color='blue', ax=axes[1])
axes[1].set_title(f'Squared YearBuilt (Skew: {Ames["Squared_YearBuilt"].skew():.5f})')
axes[1].set_xlabel('Squared YearBuilt')
axes[1].set_ylabel('Frequency')
# Cubed YearBuilt
sns.histplot(Ames['Cubed_YearBuilt'], kde=True, bins=30, color='orange', ax=axes[2])
axes[2].set_title(f'Cubed YearBuilt (Skew: {Ames["Cubed_YearBuilt"].skew():.5f})')
axes[2].set_xlabel('Cubed YearBuilt')
axes[2].set_ylabel('Frequency')
# Box-Cox Transformed YearBuilt
sns.histplot(Ames['BoxCox_YearBuilt'], kde=True, bins=30, color='red', ax=axes[3])
axes[3].set_title(f'Box-Cox Transformed YearBuilt (Skew: {Ames["BoxCox_YearBuilt"].skew():.5f})')
axes[3].set_xlabel('Box-Cox YearBuilt')
axes[3].set_ylabel('Frequency')
# Yeo-Johnson Transformed YearBuilt
sns.histplot(Ames['YeoJohnson_YearBuilt'], kde=True, bins=30, color='purple', ax=axes[4])
axes[4].set_title(f'Yeo-Johnson Transformed YearBuilt (Skew: {Ames["YeoJohnson_YearBuilt"].skew():.5f})')
axes[4].set_xlabel('Yeo-Johnson YearBuilt')
axes[4].set_ylabel('Frequency')
# Quantile Transformed YearBuilt (Normal Distribution)
sns.histplot(Ames['Quantile_YearBuilt'], kde=True, bins=30, color='green', ax=axes[5])
axes[5].set_title(f'Quantile Transformed YearBuilt (Normal Distn, Skew: {Ames["Quantile_YearBuilt"].skew():.5f})')
axes[5].set_xlabel('Quantile Transformed YearBuilt')
axes[5].set_ylabel('Frequency')
plt.tight_layout(pad=4.0)
plt.show()
以下可视化图提供了逐项比较,帮助我们更好地理解每种转换对该特征的影响。
这个可视化图清楚地展示了每种变换方法如何改变“YearBuilt”的分布,展示了其在实现更正常分布方面的效果。
想要开始学习数据科学初学者指南吗?
立即参加我的免费电子邮件速成课程(附样本代码)。
点击注册并获得课程的免费 PDF 电子书版本。
变换的统计评估
如何知道变换后的数据是否符合正态分布?
Kolmogorov-Smirnov(KS)检验是一种非参数检验,用于确定样本是否来自具有特定分布的总体。与假设数据具有特定分布形式(通常为正态分布)的参数检验不同,非参数检验不做此类假设。这一特点使得它们在数据变换的背景下非常有用,因为它有助于评估转换后的数据集与正态分布的接近程度。KS 检验将样本数据的累计分布函数(CDF)与已知分布(在这种情况下为正态分布)的 CDF 进行比较,提供一个检验统计量来量化两者之间的距离。
原假设和备择假设:
-
原假设 ( H 0 H_0 H0): 数据符合指定的分布(在本例中为正态分布)。
-
备择假设 ( H 1 H_1 H1): 数据不符合指定的分布。
在此背景下,KS 检验用于评估变换数据的经验分布与正态分布之间的拟合优度。检验统计量是经验(变换数据)和理论累计分布函数(正态分布)之间最大差异的度量。小的检验统计量表明分布是相似的。
# Import the Kolmogorov-Smirnov Test from scipy.stats
from scipy.stats import kstest
# Run the KS tests for the 10 cases
transformations = ["Log_SalePrice", "Sqrt_SalePrice", "BoxCox_SalePrice",
"YeoJohnson_SalePrice", "Quantile_SalePrice",
"Squared_YearBuilt", "Cubed_YearBuilt", "BoxCox_YearBuilt",
"YeoJohnson_YearBuilt", "Quantile_YearBuilt"]
# Standardizing the transformations before performing KS test
ks_test_results = {}
for transformation in transformations:
standardized_data = (Ames[transformation] - Ames[transformation].mean()) / Ames[transformation].std()
ks_stat, ks_p_value = kstest(standardized_data, 'norm')
ks_test_results[transformation] = (ks_stat, ks_p_value)
# Convert results to DataFrame for easier comparison
ks_test_results_df = pd.DataFrame.from_dict(ks_test_results, orient='index', columns=['KS Statistic', 'P-Value'])
print(ks_test_results_df.round(5))
上述代码打印出的表格如下:
KS Statistic P-Value
Log_SalePrice 0.04261 0.00017
Sqrt_SalePrice 0.07689 0.00000
BoxCox_SalePrice 0.04294 0.00014
YeoJohnson_SalePrice 0.04294 0.00014
Quantile_SalePrice 0.00719 0.99924
Squared_YearBuilt 0.11661 0.00000
Cubed_YearBuilt 0.11666 0.00000
BoxCox_YearBuilt 0.11144 0.00000
YeoJohnson_YearBuilt 0.11144 0.00000
Quantile_YearBuilt 0.02243 0.14717
你可以看到,KS 统计量越高,p 值越低。
-
KS 统计量: 这是样本的经验分布函数与参考分布的累计分布函数之间的最大差异。较小的值表示与正态分布的拟合程度更高。
-
p 值: 提供了在原假设下观察测试结果的概率。较低的 p 值(通常 <0.05)会拒绝原假设,表明样本分布与正态分布存在显著差异。
“SalePrice”的 Quantile 变换产生了最有前途的结果,KS 统计量为 0.00719,p 值为 0.99924,表明经过这种变换后,分布与正态分布紧密对齐。这并不令人惊讶,因为 Quantile 变换设计用于产生良好的拟合。p 值显著,因为较高的 p 值(接近 1)表明无法拒绝原假设(样本来自指定的分布),这意味着正态性良好。
类似于 Log、Box-Cox 和 Yeo-Johnson 的其他变换也改善了“SalePrice”的分布,但效果较小,这从它们较低的 p 值(范围从 0.00014 到 0.00017)中可以看出,这表明与 Quantile 变换相比,符合正态分布的程度较低。应用于“YearBuilt”的变换在实现正态性方面的效果普遍不如“SalePrice”。BoxCox 和 YeoJohnson 变换在 KS 统计量和 p 值稍微低于平方和立方变换,虽然仍然显示出明显的偏离正态性的情况。对于“YearBuilt”的 Quantile 变换表现出更有利的结果,KS 统计量为 0.02243,p 值为 0.14717,表明在正态性方面有中等程度的改善,但效果不如“SalePrice”明显。
选择正确的变换方法
选择适合处理数据偏态的正确变换方法不是一种通用的决策;它需要仔细考虑具体情况和数据特征。选择合适变换方法时,背景的重要性不容低估。以下是需要考虑的关键因素:
-
数据特征: 数据的性质(例如,是否存在零或负值)可能限制某些变换的适用性。例如,对数变换不能直接应用于零或负值,需要进行调整。
-
偏斜程度: 数据的偏斜程度影响变换的选择。较严重的偏斜可能需要更强的变换(例如,Box-Cox 或 Yeo-Johnson),而较轻微的偏斜可能通过对数或平方根变换就能得到充分解决。
-
统计属性: 选择的变换应 ideally 改善数据集的统计属性,例如规范化分布和稳定方差,这对于许多统计测试和模型是至关重要的。
-
可解释性: 变换后结果的易解释性至关重要。某些变换,如对数变换或平方根变换,允许相对简单的解释,而其他变换,如分位数变换,可能会复杂化对原始尺度的解释。
-
分析目标: 分析的最终目标—无论是预测建模、假设检验还是探索性分析—在选择变换方法时起着关键作用。变换应与后续使用的分析技术和模型相一致。
总结来说,选择合适的变换依赖于多个因素,包括但不限于对数据集的深入理解、分析的具体目标以及对模型可解释性和性能的实际影响。没有一种方法是普遍优越的;每种方法都有其权衡和适用性,具体取决于手头的场景。需要特别注意的是,Quantile Transformation,尽管通过视觉和统计测试被识别为在实现正态分布方面非常有效,但它并不像其他方法那样是线性变换。这意味着它可能会显著改变数据的结构,方式不易逆转,可能会使结果的解释和逆变换的应用变得复杂。因此,尽管在归一化方面效果显著,但在需要保持与原始数据尺度的联系或模型可解释性优先的情况下,使用时应谨慎。在大多数情况下,可能更倾向于选择在归一化效果与简洁性和可逆性之间取得平衡的变换,确保数据尽可能可解释和可管理。
进一步阅读
APIs
资源
总结
在这篇文章中,你对数据变换进行了详细探讨,重点关注它们在数据科学领域处理偏斜数据中的关键作用。通过使用‘SalePrice’和‘YearBuilt’特征的 Ames 房屋数据集的实际示例,你展示了各种变换技术——对数变换、平方根变换、Box-Cox 变换、Yeo-Johnson 变换以及分位数变换——以及它们在数据分布标准化中的影响。你的分析强调了根据数据特征、偏斜程度、统计目标、可解释性和分析的具体目标选择适当变换的必要性。
具体来说,你学到了:
-
数据变换的意义以及它们如何处理偏斜分布。
-
如何通过视觉和统计评估来比较不同变换的效果。
-
评估数据特征、偏斜程度和分析目标,以选择最适合的变换技术的重要性。
有任何问题吗?请在下面的评论中提问,我会尽力回答。
精通对角线图用于 Ames Housing 市场中的可视化和假设创建
理解房地产数据涉及探索不同的属性特征及其对住房市场趋势的影响。一个有用的工具是对角线图。这种数据可视化技术允许你发现数据集中不同特征之间的相关方向和大小。
让我们开始吧。
精通对角线图用于 Ames Housing 市场中的可视化和假设创建
照片由Juliana e Mariana Amorim提供。版权所有。
概述
本文分为三个部分;它们是:
-
探索特征关系的对角线图
-
揭示更深层次的见解:带有类别增强的对角线图
-
激发数据驱动的探究:通过对角线图生成假设
探索特征关系的对角线图
对角线图,也称为散点图矩阵,提供了数据集中多个变量之间相互作用的全面视图。与相关性热图不同,后者在颜色编码网格中表示相关系数,对角线图则描绘了实际的数据点,揭示了关系的性质,超越了仅仅是强度和方向。
为了说明这一点,让我们深入研究 Ames Housing 数据集。我们将重点关注与“SalePrice”最强相关的前五个特征。
# Import the necessary libraries
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# Load the dataset
Ames = pd.read_csv('Ames.csv')
# Calculate the correlation of all features with 'SalePrice'
correlations = Ames.corr()['SalePrice'].sort_values(ascending=False)
# Top 5 features most correlated with 'SalePrice' (excluding 'SalePrice' itself)
top_5_features = correlations.index[1:6]
# Creating the pair plot for these features and 'SalePrice'
# Adjust the size by setting height and aspect
sns.pairplot(Ames, vars=['SalePrice'] + list(top_5_features), height=1.35, aspect=1.85)
# Displaying the plot
plt.show()
如上图所示,每个子图提供了一对特征的散点图。这种可视化方法不仅允许我们观察单个变量的分布,还揭示了它们之间的复杂关系。对角线图特别擅长揭示这些关系的性质。例如,我们可以看到这些关系是线性的,表明稳步增加或减少,还是非线性的,显示更复杂的动态。它还突出了数据点聚集的簇和与整体趋势不同的离群点。
例如,“SalePrice”和“GrLivArea”之间的关系。对角线图中的散点图显示了大致的线性关系,表明“GrLivArea”增加时,“SalePrice”也会上升。然而,这并不是一个完美的线性相关——一些数据点偏离了这个趋势,表明可能还有其他因素影响售价。此外,图中还显示了一些离群点,即“GrLivArea”或“SalePrice”异常高的属性,这些可能是特殊情况或数据输入错误。
通过这种格式呈现数据,配对图超越了单纯的数值系数,提供了对数据的细致入微的视图。它们使我们能够识别数据集中的模式、趋势和异常,这对于在房地产市场做出明智决策至关重要。这些洞察对于希望理解物业价值决定因素多方面性的利益相关者尤其有益。
用我的书 《数据科学初学者指南》 来启动你的项目。它提供了自学教程和可运行的代码。
揭示更深层次的洞察:带有分类增强的配对图
在我们继续探索房地产数据可视化的过程中,我们现在重点关注通过分类变量来丰富配对图。通过引入分类维度,我们可以发现数据中的更深层次的洞察和更细致的关系。在本节中,我们将 Ames Housing 数据集中的“LotShape”转换为二元类别(规则与不规则),并将其整合到配对图中。这一增强使我们能够观察这些地块形状如何与“SalePrice”、“OverallQual”和“GrLivArea”等关键变量互动。
# Convert 'LotShape' to a binary feature: 'Regular' and 'Irregular'
Ames['LotShape_Binary'] = Ames['LotShape'].apply(lambda x: 'Regular' if x == 'Reg' else 'Irregular')
# Creating the pair plot, color-coded by 'LotShape_Binary'
sns.pairplot(Ames, vars=['SalePrice', 'OverallQual', 'GrLivArea'], hue='LotShape_Binary',
palette='Set1', height=2.5, aspect=1.75)
# Display the plot
plt.show()
结果配对图根据“规则”和“不规则”地块形状进行着色,揭示了有趣的模式。例如,我们注意到不规则地块的房屋在销售价格和居住面积上有较大的变化,这可能表明物业类型或买家偏好的多样性。此外,规则地块的整体质量(“OverallQual”)似乎变化较小,这可能暗示了这些区域在建筑标准或设计选择上的某种趋势。
这种增强的视觉工具不仅加深了我们对房地产市场动态的理解,还邀请进一步的探索。利益相关者可以尝试不同的特征组合和分类变量,将他们的分析定制为特定的兴趣或市场细分,使这种方法在房地产分析中成为多功能的资产。
激发数据驱动的询问:通过配对图生成假设
配对图不仅是可视化的强大工具,也用于数据分析中的假设生成。通过揭示数据集中的模式、趋势和异常,这些图表可以激发洞察性的问题和假设。例如,观察两个变量之间的线性关系可能会引发关于因果关系的假设,或者一个意外的数据点聚类可能促使对潜在因素的探究。从本质上讲,配对图可以作为深入、针对性的统计测试和探索的跳板。
从第一个视觉图中生成的假设(“SalePrice”与其他特征的关系):
-
假设 1:“GrLivArea”和“SalePrice”之间存在线性关系,这表明较大的居住面积直接贡献于更高的房产价值。
-
假设 2:在“SalePrice”与“GrLivArea”图中观察到的异常值可能表明独特的奢侈房产或数据录入错误,需要进一步调查。
假设 来自第二个视觉(将“LotShape”作为二元类别纳入):
-
假设 3:不规则地块形状的房产在销售价格上的差异性比规则地块形状更大,这可能是由于房产类型的多样性或独特特征。
-
假设 4:规则形状地块上的房产总体质量趋于更一致,这表明这些区域可能存在标准化的建筑实践或买家偏好。
这些假设源自于配对图中观察到的模式,然后可以通过更严格的统计方法进行验证或否定初步观察。这种方法强调了配对图作为假设驱动的数据分析基础步骤的实用性。
想要开始数据科学初学者指南吗?
立即获取我的免费电子邮件速成课程(附样本代码)。
点击注册并获取课程的免费 PDF 电子书版。
进一步阅读
本部分提供了更多资源,如果你想深入了解这一主题。
资源
总结
在我们探索 Ames 住房数据集的过程中,我们踏上了配对图的世界,揭示了数据讲述的复杂故事。这次旅程不仅突显了视觉分析在房地产分析中的重要性,还展示了配对图在揭示复杂关系和指导数据驱动假设生成方面的强大能力。具体来说,你学习了:
-
配对图在说明各种住房市场特征之间的关系方面的有效性,尤其是关于“SalePrice”。
-
如何将诸如“LotShape”这样的分类变量整合到配对图中,以提供更深刻的洞察并揭示数据中的微妙趋势。
-
配对图的潜力作为生成假设的基础,为更高级的统计分析和知情决策奠定了基础。
你有任何问题吗?请在下面的评论中提问,我会尽力回答。
本地使用 Gemma 2 的三种方式
原文:
machinelearningmastery.com/3-ways-of-using-gemma-2-locally/
作者提供的图片
在 Gemma 1 成功推出后,Google 团队推出了一个更先进的模型系列,称为 Gemma 2。这个新的大型语言模型(LLMs)系列包括 90 亿(9B)和 270 亿(27B)参数的模型。Gemma 2 提供比其前身更高的性能和更大的推理效率,同时具有显著的安全性提升。这两款模型都优于 Llama 3 和 Gork 1 模型。
在本教程中,我们将了解三种应用程序,这些应用程序将帮助你更快地在本地运行 Gemma 2 模型。要在本地体验最先进的模型,你只需安装应用程序,下载模型并开始使用。就是这么简单。
1. Jan
从官方网站下载并安装 Jan。Jan 是我最喜欢的运行和测试各种开源及专有 LLM 的应用程序。它非常容易设置,并且在导入和使用本地模型方面具有很高的灵活性。
启动 Jan 应用程序并进入 Model Hub 菜单。然后,将 Hugging Face 仓库的以下链接粘贴到搜索栏中并按回车:bartowski/gemma-2-9b-it-GGUF。
作者提供的图片
你将被重定向到一个新窗口,在那里你可以选择不同的量化版本。我们将下载“Q4-K-M”版本。
作者提供的图片
从右侧面板的模型菜单中选择已下载的模型并开始使用。
这个量化模型的当前版本每秒提供 37 个令牌,但如果使用不同的版本,你的速度可能会更快。
作者提供的图片
2. Ollama
访问官方网站下载并安装 Ollama。它在开发者和熟悉终端及 CLI 工具的人中非常受欢迎。即使是新用户,也很容易设置。
安装完成后,请启动 Ollama 应用程序并在你喜欢的终端中输入以下命令。我在 Windows 11 上使用 Powershell。
$ ollama run gemma2
根据你的互联网速度,下载模型大约需要半小时。
作者提供的图片
下载完成后,你可以开始提示并在终端中使用它。
作者提供的图片
通过从 GGUF 模型文件导入来使用 Gemma2
如果你已经有了一个 GGUF 模型文件并想与 Ollama 一起使用,那么你首先需要创建一个名为“Modelfile”的新文件,并输入以下命令:
FROM ./gemma-2-9b-it-Q4_K_M.gguf
之后,使用 Modelfile 创建模型,该文件指向你目录中的 GGUF 文件。
$ ollama create gemma2 -f Modelfile
当模型转移成功完成后,请输入以下命令开始使用它。
$ ollama run gemma2
作者提供的图片
3. Msty
从官方网站下载并安装 Msty。Msty 是一个新兴的竞争者,正成为我最喜欢的应用程序。它提供了大量功能和模型。你甚至可以连接到专有模型或 Ollama 服务器。它是一个简单而强大的应用程序,你应该试一试。
安装应用程序成功后,请启动程序并通过点击左侧面板上的按钮导航到“本地 AI 模型”。
作者提供的图片
点击“下载更多模型”按钮,并在搜索栏中输入以下链接:bartowski/gemma-2-9b-it-GGUF。确保你已选择 Hugging Face 作为模型中心。
作者提供的图片
下载完成后,开始使用它。
作者提供的图片
使用 Msty 与 Ollama
如果你想在聊天机器人应用程序中使用 Ollama 模型而不是终端,可以使用 Msty 的与 Ollama 连接选项。这很简单。
- 首先,去终端并启动 Ollama 服务器。
$ ollama serve
复制服务器链接。
>>> </b>listen tcp 127.0.0.1:11434
-
导航到“本地 AI 模型”菜单,并点击右上角的设置按钮。
-
然后,选择“远程模型提供者”并点击“添加新提供者”按钮。
-
接下来,将模型提供者选择为“Ollama 远程”,并输入 Ollama 服务器的服务端点链接。
-
点击“重新获取模型”按钮,选择“gemma2:latest”,然后点击“添加”按钮。
作者提供的图片
- 在聊天菜单中,选择新的模型并开始使用它。
作者提供的图片
结论
我们评测的这三款应用程序功能强大,具有大量功能,将提升你使用 AI 模型的本地体验。你需要做的就是下载应用程序和模型,其余的都很简单。
我使用 Jan 应用程序测试开源 LLM 的性能,并生成代码和内容。它速度快且私密,我的数据从未离开过我的笔记本电脑。
在本教程中,我们学习了如何使用 Jan、Ollama 和 Msty 本地运行 Gemma 2 模型。这些应用程序具有重要的功能,将提升你使用本地 LLM 的体验。
我希望你喜欢我的简短教程。 我喜欢分享我热衷并且经常使用的产品和应用。
房地产中的假设检验:深入研究使用 Ames 房屋数据集的假设检验
原文:
machinelearningmastery.com/a-dive-into-hypothesis-testing/
在进行推断统计时,你通常需要测试你的假设。确实,有一种定量测试你想到的假设的方法。通过使用 Ames 房屋数据集,你将深入探讨假设检验的概念,并探索空调的存在是否影响房屋的销售价格。
让我们开始吧。
房地产中的假设检验:深入研究使用 Ames 房屋数据集的假设检验
图片由亚历克斯·斯陶丁格提供。保留部分权利。
概述
本文通过以下几个部分展开:
-
假设检验在推断统计中的作用。
-
假设检验是如何工作的?
-
空调是否影响销售价格?
假设检验在推断统计中的作用
推断统计使用数据样本来对所抽取的总体做出推断。假设检验是推断统计的一个基本组成部分,当基于样本数据对总体做出有根据的决策时,特别是在研究整个总体不可行的情况下,假设检验是至关重要的。假设检验是一种关于数据的陈述方法。
想象一下你发现了一个声明,称有空调的房子比没有空调的房子售价更高。为了验证这一声明,你会收集房屋销售数据,并分析是否存在基于空调存在与否的价格显著差异。这一过程即是通过样本数据测试关于总体的声明或假设,称为假设检验。从本质上讲,假设检验允许我们基于样本的证据以及观察到的效果是否是偶然发生的可能性,做出有根据的决定(即拒绝或不拒绝一个初始假设)。
启动你的项目,请参阅我的书籍数据科学入门指南。它提供了自学教程和可运行的代码。
假设检验是如何工作的?
假设检验是一种推断统计的方法论,你从关于总体参数的初始声明(假设)开始。然后,你使用样本数据来确定是否有足够的证据来拒绝这个初始声明。假设检验的组成部分包括:
-
原假设 ( H 0 H_0 H0): 默认状态为没有效果或没有差异。你要测试的陈述。
-
替代假设 ( H a H_a Ha): 你想要证明的内容。它是当原假设错误时你所相信的内容。
-
检验统计量: 从样本数据中计算出的一个值,用于检验原假设。
-
p 值: 在原假设情况下,样本中观察到的效应发生的概率。
进行假设检验就像侦探工作:通常,你假设某事应该发生( H 0 H_0 H0),但你怀疑实际上发生了其他事情( H 1 H_1 H1)。然后你收集证据(检验统计量)来论证为何 H 0 H_0 H0 不合理;因此 H 1 H_1 H1 应该是事实。
在典型的假设检验中:
-
你陈述原假设和替代假设。你应该仔细设计这些假设,以反映对现实的合理假设。
-
你选择一个显著性水平( α \alpha α);在统计假设检验中,通常使用 α = 0.05 \alpha=0.05 α=0.05。
-
你收集并分析数据,以获得我们的检验统计量和 p 值,基于 H 0 H_0 H0 的情况。
-
你基于 p 值做出决定:当且仅当 p 值小于 α \alpha α 时,你才会拒绝原假设并接受替代假设。
让我们来看一个示例,展示这些步骤是如何执行的。
空调是否影响销售价格?
基于 Ames 数据集,我们想知道空调的存在是否会影响价格。
为了探讨空调对销售价格的影响,你将设定我们的假设为:
-
H 0 H_0 H0:带有空调的房屋的平均销售价格与没有空调的房屋相同。
-
H a H_a Ha:带有空调的房屋的平均销售价格与没有空调的房屋不同。
在进行假设检验之前,我们先可视化数据,以获得初步了解。
# Loading the dataset and essential libraries
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
Ames = pd.read_csv('Ames.csv')
# Data separation
ac_prices = Ames[Ames['CentralAir'] == 'Y']['SalePrice']
no_ac_prices = Ames[Ames['CentralAir'] == 'N']['SalePrice']
# Setting up the visualization
plt.figure(figsize=(10, 6))
# Histograms for sale prices based on air conditioning
# Plotting 'With AC' first for the desired order in the legend
plt.hist(ac_prices, bins=30, alpha=0.7, color='blue', edgecolor='blue', lw=0.5,
label='Sales Prices With AC')
mean_ac = np.mean(ac_prices)
plt.axvline(mean_ac, color='blue', linestyle='dashed', linewidth=1.5,
label=f'Mean (With AC): ${mean_ac:.2f}')
plt.hist(no_ac_prices, bins=30, alpha=0.7, color='red', edgecolor='red', lw=0.5,
label='Sales Prices Without AC')
mean_no_ac = np.mean(no_ac_prices)
plt.axvline(mean_no_ac, color='red', linestyle='dashed', linewidth=1.5,
label=f'Mean (Without AC): ${mean_no_ac:.2f}')
plt.title('Distribution of Sales Prices based on Presence of Air Conditioning', fontsize=18)
plt.xlabel('Sales Price', fontsize=15)
plt.ylabel('Number of Houses', fontsize=15)
plt.legend(loc='upper right')
plt.tight_layout()
plt.show()
重叠直方图比较销售价格
上述代码调用了 plt.hist()
两次,使用不同的数据来显示两个重叠的直方图,一个用于带空调的销售价格分布,另一个用于没有空调的分布。根据这些视觉效果,可以做出以下几个观察:
-
明显的峰值: 两个分布都展示了明显的峰值,这表明了各自类别中最频繁的销售价格。
-
平均销售价格: 带有空调的房屋的平均销售价格高于没有空调的房屋,如垂直虚线所示。
-
分布和偏态: 带有空调的房屋销售价格分布呈现出轻微的右偏,这表明尽管大多数房屋以较低价格出售,但也有一些房产的价格显著较高。相比之下,没有空调的房屋价格分布更为紧凑,价格范围较小。
-
重叠: 尽管均值有所不同,但有空调和没有空调的房屋在价格范围上存在重叠。这表明,虽然空调可能会影响价格,但其他因素也在决定房屋价值方面发挥作用。
基于这些见解,有空调的房子似乎与更高的销售价格相关。下一步将是执行假设检验,以数字方式确定这种差异是否显著。
# Import an additional library
import scipy.stats as stats
# Performing a two-sample t-test
t_stat, p_value = stats.ttest_ind(ac_prices, no_ac_prices, equal_var=False)
# Printing the results
if p_value < 0.05:
result = "reject the null hypothesis"
else:
result = "fail to reject the null hypothesis"
print(f"With a p-value of {p_value:.5f}, we {result}.")
这表明:
With a p-value of 0.00000, we reject the null hypothesis.
p 值小于 α \alpha α。p 值表明,在 H 0 H_0 H0 下,价格差异很可能不是偶然的。这表明有空调的房子的平均销售价格与没有空调的房子之间存在统计学上显著的差异。这与我们从直方图中的视觉观察一致。因此,空调的存在似乎确实对 Ames 数据集中的房子销售价格产生了显著影响。
这个 p 值是使用 t 检验计算的。它是一种统计量,旨在比较两个组的均值。有许多统计方法可用,t 检验在这里是合适的,因为我们的假设 H 0 H_0 H0、 H a H_a Ha 关注的是平均销售价格。
请注意,上述定义的备择假设
H
a
H_a
Ha 可以更改。你可以将其设为“有空调的房子的平均销售价格低于没有空调的房子”;然而,这与现实情况相悖。你也可以将其设为“有空调的房子的平均销售价格高于没有空调的房子”;在这种情况下,你应当将代码中的 t 检验修改为包括额外的参数 alternative='greater'
:
# Performing a one-sided t-test
t_stat, p_value = stats.ttest_ind(ac_prices, no_ac_prices, equal_var=False, alternative='greater')
# Printing the results
if p_value < 0.05:
result = "reject the null hypothesis"
else:
result = "fail to reject the null hypothesis"
print(f"With a p-value of {p_value:.5f}, we {result}.")
With a p-value of 0.00000, we reject the null hypothesis.
这将双侧 t 检验更改为单侧 t 检验,但结果是相同的。从双侧 t 检验转换为单侧 t 检验但得出相同的结论,意味着我们从一开始就对差异的方向有明确的预期,或者数据强烈支持某一方向的差异,使得两种检验类型的结果一致。
原假设 ( H 0 H_0 H0) 和备择假设 ( H a H_a Ha) 的设定是统计检验设计的基础,它影响检验的方向性(单侧与双侧)、结果的解释(我们如何理解 p 值和证据)以及决策过程(尤其是在 p 值接近显著性水平 α \alpha α 时)。这一框架不仅决定了我们测试的内容,还决定了我们如何解释和采取统计证据。
想要开始学习数据科学的初学者指南吗?
立即参加我的免费电子邮件速成课程(包含示例代码)。
点击注册并获得课程的免费 PDF 电子书版本。
进一步阅读
在线
-
学生 t 检验 维基百科
资源
总结
在这次探索中,你深入了解了使用 Ames Housing 数据集进行假设检验的世界。你研究了空调的存在如何影响房屋的售价。通过严格的统计检验,你发现有空调的房屋售价往往高于没有空调的房屋,这一结果具有统计学意义。这不仅突显了像空调这样的设施在房地产市场中的重要性,还展示了基于数据做出明智决策的假设检验的力量。
具体来说,你学到了:
-
假设检验在推断统计中的重要性。
-
如何通过详细的假设检验方法设置和评估原假设与备择假设。
-
假设检验在现实世界情境中的实际应用,以 Ames 住房市场中空调对房产价值的影响为例。
你有什么问题吗?请在下面的评论中提问,我会尽力回答。
使用 ChatGPT 进行高级研究技术
原文:
machinelearningmastery.com/advanced-techniques-for-research-with-chatgpt/
研究一直是人类进步的关键,并且在过去几年中得到了极大的发展。随着先进技术的出现,新的工具和技术已经出现,以进行更高效的研究,并保持在知识前沿。ChatGPT 就是这样的技术之一,它是一个大型语言模型,使用深度学习方法生成类似人类的回应。ChatGPT 能够理解和生成文本的卓越能力使它成为一个不可或缺的工具,可以提升你的研究工作。它通过提供全面的见解来节省时间和资源,从而提高了你的研究生产力。然而,研究人员必须小心使用 ChatGPT 的伦理问题,确保他们的研究准确无偏。
在这篇文章中,你将探索改进研究的高级技术。特别是,
-
研究数据的分析与解读
-
执行文献综述与识别研究空白
开始使用 ChatGPT,可参考我的书籍 《利用 ChatGPT 最大化生产力》。它提供了实际应用案例和提示示例,旨在帮助你快速上手 ChatGPT。
开始吧。
使用 ChatGPT 进行高级研究技术。
图片由 Adrian Tam 使用 Stable Diffusion 生成。保留部分权利。
概述
本文分为三个部分,它们是:
-
研究数据的分析与解读
-
执行文献综述与识别研究空白
-
研究人员的额外提示
研究数据的分析与解读
一位小企业主希望分析客户满意度数据,以改善客户服务。他们使用了包含 10 个问题的李克特量表问卷从 50 名客户那里收集了这些数据。这些数据是从 1 到 5 的数值评分,其中 1 表示“非常不满意”,而 5 表示“非常满意”。使用传统方法解读这些原始数据将非常耗时,并且需要专门的软件技能。在这种情况下,你可以使用 ChatGPT 来帮助你理解数据。
你将看到我们将如何提问来协助这位企业主。在继续进行提示之前,下面是我们将要处理的数据快照:
客户 ID | Q1 | Q2 | Q3 | Q4 | Q5 | Q6 | Q7 | Q8 | Q9 | Q10 |
---|---|---|---|---|---|---|---|---|---|---|
1 | 4 | 5 | 3 | 5 | 4 | 3 | 4 | 4 | 5 | 3 |
2 | 3 | 4 | 2 | 4 | 3 | 2 | 3 | 3 | 4 | 2 |
3 | 5 | 5 | 4 | 5 | 5 | 5 | 4 | 5 | 5 | 4 |
4 | 2 | 3 | 2 | 4 | 2 | 2 | 3 | 3 | 2 | 2 |
5 | 4 | 4 | 3 | 4 | 4 | 4 | 4 | 4 | 4 | 3 |
6 | 3 | 4 | 2 | 4 | 3 | 3 | 3 | 3 | 4 | 2 |
7 | 1 | 2 | 1 | 2 | 1 | 1 | 2 | 2 | 1 | 1 |
. | . | . | . | . | . | . | . | . | . | . |
. | . | . | . | . | . | . | . | . | . | . |
49 | 2 | 2 | 1 | 2 | 1 | 1 | 2 | 2 | 1 | 1 |
50 | 3 | 4 | 2 | 4 | 3 | 3 | 3 | 3 | 4 | 2 |
步骤 1:数据分析与探索
数据探索是数据分析中的一个关键步骤,它帮助你理解数据并识别关键见解。在提示 ChatGPT 之前,请列出你希望回答的具体问题。将这些问题纳入考虑将引导数据探索过程。以下是业务所有者提供给 ChatGPT 的最终提示:
我希望你能帮助我进行我收集的客户满意度评分数据集的初步数据探索。请提供以下信息:
能否提供客户满意度评分数据集的汇总统计信息,包括评分的范围、平均值、中位数和众数?
每个问题中,多少客户给出了最高评分(5),多少客户给出了最低评分(1)?
数据集:{}
以下是 ChatGPT 的回应:
为了进行客户满意度评分数据集的初步数据探索,我们可以从计算汇总统计信息开始,包括评分的范围、平均值、中位数和众数。
以下是数据集中每个问题的汇总统计信息:
问题 1(Q1):
范围:4(5 – 1)
平均值:3.08
中位数:3
众数:4(出现频率最高) …… 直到第 10 个问题(Q10)
以下是你提供的客户满意度评分数据集的汇总统计信息:
范围:评分范围为 1 到 5。
平均值:所有客户和问题的平均评分为 3.36。
中位数:中位数评分为 4.0,这意味着一半的评分低于 4,另一半高于 4。
众数:众数代表数据集中最常见的评分。在这种情况下,有多个众数,其中评分为 4 的频率最高。
现在,让我们找出每个问题中给予最高评分(5)和最低评分(1)的客户数量:
对于问题 1(Q1):
给出评分为 5 的客户数量:5
给出评分为 1 的客户数量:3 …… 直到第 10 个问题(Q10)
请注意,上述计数基于你提供的数据集。如果你有更多数据,计数可能会有所不同。
步骤 2:解释关键见解
现在,你对数据有了一个总体概述,让我们挖掘公司可以利用的关键见解以及客户投诉的常见原因。考虑到上述情况,业务所有者制定了一个新提示,并将其输入 ChatGPT。步骤 1 之后的跟进提示如下:
基于上述统计信息,我可以从数据中得出哪些关键见解?你还可以提供以下信息:
1. 基于可用数据,客户忠诚度的关键驱动因素是什么?
2. 客户投诉或负面反馈的常见原因是什么?
由于我们考虑的是虚拟数据,问题就像一个黑匣子,ChatGPT 无法向我们提供关于如何改善策略的建议,但会指出改进的领域。
下面是 ChatGPT 的回应:
根据提供的统计数据,我们可以从数据中得出以下关键见解:
平均评分:所有客户和问题的平均评分为 3.36,略低于 5 的中点。这表明整体客户满意度是中等偏下的。
正面评价:最频繁的评分是 4 分,这表明许多客户总体上对服务或产品感到满意。
负面评价:有一些客户给出了对某些问题的最低 1 分评价。这表明有些地方需要改进以解决客户的关切。
问题 10(Q10):这个问题收到了最多的最低评分(5 名客户给出了 1 分评分)。值得调查该问题中提出的具体问题,以确定改进的潜在领域。
现在,让我们分析数据,根据现有信息识别客户忠诚度的关键驱动因素。为了确定这一点,我们可以查看那些获得最多 5 分评分的问题:
问题 2(Q2):所有客户均给出了 5 分的评分。这表明该问题涉及的方面是客户忠诚度的关键驱动因素。不幸的是,没有实际的问题内容,很难确定具体的驱动因素。
问题 1、4、5、6、7、8 和 9:这些问题也收到了所有客户的 5 分评分。与 Q2 类似,没有了解这些问题的具体内容,无法确定忠诚度的具体驱动因素。
关于客户投诉或负面反馈的常见原因,数据显示问题 10(Q10)收到了最多的最低评分(5 名客户给出了 1 分评分)。这表明 Q10 中涉及的具体问题导致了客户的不满。为了确定负面反馈的常见原因,必须查看问题 10 的内容,并分析客户提供的反馈。没有这些信息,我们无法提供关于常见投诉的具体见解。
为了获得更深入的见解和更全面的数据理解,建议查看实际的问题,并分析客户提供的定性反馈(如果有的话)。这将提供更多背景信息,并更准确地识别忠诚度的关键驱动因素和投诉的常见原因。
你已经看到 ChatGPT 如何帮助商业决策者以便做出基于数据的决策。然而,研究人员应注意避免在制定提示或输入数据时使用偏见语言。这可能导致偏颇的结果。使用代表整个群体的高质量训练数据也有助于确保研究准确且不偏颇。
执行文献综述与识别研究空白
Zeenat 是一名研究生研究员。她的目标是对可再生能源资源及其整合到电网中的情况进行文献综述。她希望识别该领域中的潜在空白,以帮助她制定研究问题,并协助她在文献综述过程中。你将看到 Zeenat 与 ChatGPT 之间的 1 对 1 对话:
1. 可再生能源技术:许多可再生能源技术正在被研究和部署,包括太阳能光伏(PV)系统、风力涡轮机、水电、生物质、地热能和潮汐能。研究人员正在调查这些技术的技术方面、效率和可扩展性。
2. 电网整合挑战:研究的一个主要焦点是理解和解决与将可再生能源整合到电网中相关的挑战。这些挑战包括可再生发电的间歇性和变动性、电网稳定性、电压控制、频率调节以及电力质量问题。
…等等…
ChatGPT 的知识截止日期为 2021 年 9 月,因此 ChatGPT 可能不知道最近发生的事件。它提供了对当前挑战和已完成工作的全面概述,但回答也应从其他来源验证。让我们回到 Zeenat 与 ChatGPT 的对话:
Zeenat: 你能提供一份关于可再生能源整合到电网中最常被引用的前 10 篇论文的清单吗?
1. “电力系统稳定性与控制”由普拉巴·昆杜尔著作
2. “大规模可再生电力生成:整合与可持续性”由彼得·德罗伊格著作
3. “电力系统分析”由哈迪·萨阿达特著作
4. “可再生能源来源与气候变化缓解”由奥特马尔·埃登霍费尔等人著作。
5. “可再生能源整合:电网中的变异性、不确定性和灵活性的实际管理” 由Lawrence E. Jones 编著
6. “智能电网:实现能源效率和需求响应” 由Clark W. Gellings 编著
7. “可再生能源电网整合:技术与监管问题” 由Lawrence E. Jones 编著
8. “可再生和高效电力系统” 由Gilbert M. Masters 编著
9. “可再生能源:可持续未来的动力” 由Godfrey Boyle 编著
10. “可再生能源整合:挑战与解决方案” 由Fereidoon P. Sioshansi 编著
请注意,这个列表并不详尽,可能还有其他在该领域被高度引用的论文未被包括在内。我建议咨询学术数据库,如 Google Scholar 或 Scopus,以找到最新和最全面的关于可再生能源整合到电网中的高被引论文列表。
收集最被引用和最有影响力的论文是耗时的,特别是当信息分散在各种资源中时。然而,通过使用 ChatGPT 作为研究助手,你可以节省大量时间。现在你已经拥有了前 10 篇被引用最多的论文列表,Zeenat 需要识别出可能的研究空白,以作为她论文的基础。
Zeenat:根据当前的研究,整合可再生能源到电网中的主要挑战和研究空白是什么?
ChatGPT:将可再生能源源整合到电网中面临几个挑战和研究空白,这些问题正在被研究人员和行业专家积极解决。以下是一些主要挑战和研究领域:
1. 电网稳定性:可再生能源源(如太阳能和风能)的间歇性特征可能影响电网稳定性。开发先进的控制和预测技术有助于解决这一问题。
2. 能源存储:需要高效且成本效益高的能源存储解决方案,以储存过剩的可再生能源,以便在发电低迷期间使用。
3. 电网管理:随着可再生能源的普及,对更好的电网管理技术的需求增加,例如需求响应和分布式能源资源管理。
4. 监管框架:解决与可再生能源整合相关的监管挑战,如电网接入、定价和激励措施,仍然是一个重要的研究领域。
5. 技术创新:持续研究能够提高可再生能源发电和储存效率及成本效益的新技术和材料至关重要。
6. 系统整合:需要研究将可再生能源源与现有电力基础设施整合,包括不同能源源和电网组件之间的相互作用。
这些是将可再生能源来源整合到电网中的一些关键挑战和研究空白。研究人员、政策制定者和行业利益相关者正在积极解决这些挑战,并开发创新解决方案,以加速向可持续和基于可再生能源的电网过渡。
在 ChatGPT 的帮助下,Zeenat 能够理解当前的研究状态,并识别出潜在的研究空白,这些空白帮助她为她的论文制定研究问题。但你需要关注其他重要的考虑因素,而不仅仅是知识限制,具体如下:
-
准确性和可靠性: ChatGPT 是一个语言模型,因此其回应不能宣称 100% 准确。你需要交叉验证你的答案并咨询其他来源。
-
伦理与偏见: 研究人员应努力保持伦理研究标准,并注意 ChatGPT 回应中的潜在偏见。
研究人员的附加提示
本附加部分包含研究人员可以使用的提示,以便使他们的研究过程更可管理。从文献综述到数据收集,再到结果撰写,你可以使用这些提示来简化你的研究工作流程:
生成主题想法
“你能建议 5 个与[你的兴趣领域]相关的重要未解问题吗?这些问题将推动[特定子领域或主题]的当前知识状态前进。”
研究方法学与数据收集技术
“你能建议最适合研究[研究主题]的研究方法和数据收集技术吗?请包括它们的优缺点,以及每种方法最适用的情况。”
撰写强有力的引言、论文陈述与结论
“对于我的[研究论文]关于[研究主题],在撰写强有力的引言、明确的论文陈述和有说服力的结论方面,有哪些有效的策略?请提供指导性问题和构建这些元素的思路,以确保它们有效且与研究目标一致。”
校对你的研究论文
“校对和编辑我的{研究论文},查找语法、标点、重复词汇和拼写错误。请提供改进研究论文可读性和流畅性的建议。”
生成合成数据
“我希望你生成一个关于{数据集内容?}的数据集,包含{记录数量}个具有以下特征的合成记录。”
{领域名称}({数据类型 / 范围})……等等。
{数据集的特殊说明}
数据应该是现实的和可信的,不应明显伪造或随机生成。将输出格式化为逗号分隔值(CSV)文件,文件头行列出字段名称和{数据集编号}数据行。”
总结
尽管 ChatGPT 可以是一个有用的资源,但实际的人类研究和研究人员对特定主题的理解与专业知识仍然对高质量的研究至关重要。以下是本章的关键要点:
-
ChatGPT 可以帮助协助研究任务,让你能更多地专注于实际研究,而不是其他事务。提供了示例提示和实例,以演示它如何在研究过程的不同阶段提供帮助。
-
研究人员应仔细设计提示,并提供足够的细节和背景,以指导 ChatGPT 生成相关且有价值的回答。
-
研究人员必须对其工作的准确性和可靠性负责。他们应该遵守在研究中使用基于人工智能的辅助工具的伦理考虑。
数据科学入门(7 天迷你课程)
原文:
machinelearningmastery.com/beginning-data-science-7-day-mini-course/
数据科学使用数学来分析数据、提炼信息并讲述故事。数据科学的结果可能只是严格验证一个假设,或从数据中发现一些有用的属性。你可以在数据科学中使用许多工具,从基本统计学到复杂的机器学习模型。即使是最常见的工具,也可以在数据科学项目中发挥出色的作用。
在这个 7 部分的速成课程中,你将通过示例学习如何进行数据科学项目。这个迷你课程专注于数据科学的核心内容。假设你已经收集了数据并做好了使用准备。编写网络爬虫和验证你收集的数据可能是一个大话题;这不在本课程的范围之内。这个迷你课程是为那些已经熟悉 Python 编程并愿意学习数据科学常用工具(如 pandas 和 matplotlib)的从业人员准备的。你将看到这些工具如何提供帮助,更重要的是,学习如何从你拥有的数据中得出定量支持的结论。让我们开始吧。
数据科学初学者指南(7 天迷你课程)
图片由 Eduardo Soares 提供。版权所有。
这个迷你课程适合谁?
在我们开始之前,让我们确保你来对了地方。下面的列表提供了一些关于本课程设计对象的基本指南。如果你不完全符合这些条件也不要惊慌;你可能只需要在某个方面稍作复习以跟上进度。
-
能够编写一些代码的开发人员。这意味着你可以用 Python 完成任务,并且知道如何在工作站上设置生态系统(这是一个前提条件)。这并不意味着你是一个编码高手,但你不怕安装包和编写脚本。
-
掌握一些统计学的开发人员。这意味着你了解一些基本的统计工具,并且不怕使用它们。这并不意味着你是统计学博士,但如果遇到术语,你可以查找并学习。
-
了解一些数据科学工具的开发人员。在数据科学中,使用 Jupyter notebook 是很常见的。如果使用 pandas 库处理数据会更容易。这只是其中的一部分。你不需要对任何库成为专家,但你需要对调用不同的库和编写代码以操作数据感到舒适。
这个迷你课程不是一本数据科学教科书。而是一个项目指南,它将你从一个基础知识较少的开发人员,逐步带到能够自信展示如何完成数据科学项目的开发人员。
迷你课程概览
本迷你课程分为 7 部分。
每节课的设计时间大约是 30 分钟。你可能会更快完成某些部分,也可能会选择深入研究,花费更多时间。
你可以按照自己喜欢的速度完成每一部分。一个舒适的安排可能是每天完成一节课,持续七天。强烈推荐。
接下来 7 节课你将学习以下内容:
-
第 1 课:获取数据
-
第 2 课:缺失值
-
第 3 课:描述性统计
-
第 4 课:探索数据
-
第 5 课:可视化相关性
-
第 6 课:假设检验
-
第 7 课:识别异常值
这将非常有趣。
不过你得做些工作:一点阅读、研究和编程。你想学会如何完成一个数据科学项目,对吧?
在评论中发布你的结果;我会为你加油!
坚持住;不要放弃。
第 01 课:获取数据
我们将用于本迷你课程的数据集是“Kaggle 上提供的‘所有国家数据集’”:
这个数据集描述了几乎所有国家的人口、经济、地理、健康和政治数据。这类数据集中最著名的可能是 CIA 世界概况。抓取世界概况中的数据应该会给你更多全面和最新的数据。然而,使用这个 CSV 格式的数据集可以在构建你的网页抓取器时节省很多麻烦。
下载Kaggle 上的这个数据集(你可能需要注册一个账户),你会找到 CSV 文件All Countries.csv
。让我们用 pandas 检查这个数据集。
import pandas as pd
df = pd.read_csv("All Countries.csv")
df.info()
上述代码将把一个表格打印到屏幕上,如下所示:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 194 entries, 0 to 193
Data columns (total 64 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 country 194 non-null object
1 country_long 194 non-null object
2 currency 194 non-null object
3 capital_city 194 non-null object
4 region 194 non-null object
5 continent 194 non-null object
6 demonym 194 non-null object
7 latitude 194 non-null float64
8 longitude 194 non-null float64
9 agricultural_land 193 non-null float64
...
62 political_leader 187 non-null object
63 title 187 non-null object
dtypes: float64(48), int64(6), object(10)
memory usage: 97.1+ KB
在上面,你可以看到数据集的基本信息。例如,在顶部,你知道这个 CSV 文件中有 194 条记录(行)。表格告诉你有 64 列(从 0 到 63 索引)。一些列是数值型的,比如纬度,另一些则不是,比如 capital_city。pandas 中的数据类型“object”通常意味着它是字符串类型。你还知道有一些缺失值,比如在agricultural_land
中,194 条记录中只有 193 个非空值,这意味着这一列中有一行缺失值。
让我们更详细地查看数据集,例如以前五行作为样本:
df.head(5)
这将以表格形式显示数据集的前五行。
你的任务
这是数据集的基本探索。但是,使用head()
函数可能并不总是合适(例如,当输入数据已排序时)。还有tail()
函数用于类似的目的。然而,运行df.sample(5)
通常会更有帮助,因为它是随机抽取 5 行。尝试这个函数。此外,如你从上述输出中所见,列被截断到屏幕宽度。如何修改上述代码以显示样本的所有列?
提示:pandas 中有一个to_string()
函数,你也可以调整通用打印选项display.max_columns
。
在下一个课时,你将学习如何检查数据中的缺失值。
课时 02:缺失值
在分析数据之前,了解数据的情况非常重要。在 pandas 中,浮点型列可能会将缺失值表示为NaN
(“不是一个数字”),并且这些值的存在会破坏许多函数。
在 pandas 中,你可以通过isnull()
或notnull()
来查找缺失值。这些函数用于检查值是否为 null,包括 Python 的None
和浮点型的NaN
。返回值为布尔值。如果应用于列,你会得到一列 True 或 False。求和结果是 True 值的数量。
在下面,你可以使用isnull()
来查找缺失值,然后对结果进行求和以计算其数量。你可以对结果进行排序,以查看哪些列缺失值最多,哪些列缺失值最少。
print(df.isnull().sum().sort_values(ascending=False))
你将看到上述打印内容:
internally_displaced_persons 121
central_government_debt_pct_gdp 74
hiv_incidence 61
energy_imports_pct 56
electricty_production_renewable_pct 56
...
land_area 0
urban_population_under_5m 0
rural_land 0
urban_land 0
country 0
Length: 64, dtype: int64
在上述内容中,你可以看到某些列没有缺失值,例如国家名称。缺失值最多的列是internally_displaced_persons
,这是难民的人口统计信息。如你所见,这并不正常,合理的情况是大多数国家没有这样的群体。因此,当你处理时,可以将缺失值替换为零。这是利用领域知识进行插补的一个例子。
为了可视化缺失值,你可以使用 Python 包missingno
。它有助于展示缺失值的分布情况:
import missingno as msno
import matplotlib.pyplot as plt
msno.matrix(df, sparkline=False, fontsize=12)
plt.show()
上述图表显示,某些国家(行)和一些属性(列)有大量的缺失值。你可以大致猜测图表中的哪一列对应internally_displaced_persons
。缺失值较多的国家可能是因为这些国家没有收集这些统计数据。
你的任务
并非所有的缺失值都应该用零来替代。另一种策略是用均值替换缺失值。你能找到这个数据集中另一个适合用均值替换缺失值的属性吗?此外,如何在 pandas DataFrame 中替换缺失值?
在下一个课时,你将学习如何使用基本统计数据来探索数据。
课时 03:描述性统计
给定一个 pandas DataFrame,查看描述性统计是一个重要的第一步。在代码中,你可以使用 DataFrame 的describe()
函数:
print(df.describe())
这显示了每个数值属性的均值、标准差、最小值、最大值和四分位数。非数值列不会在输出中报告。你可以通过打印列的集合并进行比较来验证这一点:
print(df.columns)
print(df.describe().columns)
数据集中有很多列。要查看某一列的描述性统计信息,你可以将其输出过滤为 DataFrame:
print(df.describe()["inflation"])
这会打印:
count 184.000000
mean 13.046591
std 25.746553
min -6.687320
25% 4.720087
50% 7.864485
75% 11.649325
max 254.949000
Name: inflation, dtype: float64
这与定义df2=df.describe()
然后提取df2["inflation"]
是一样的。如果列中有缺失值,描述性统计数据会通过跳过所有缺失值来计算。
你的任务
从之前的示例继续,你可以通过检查df["inflation"].isnull().sum()
是否为零来判断inflation
列中是否存在缺失值。均值可以通过df["inflation"].mean()
来计算。你怎么验证这个均值是否跳过了所有的缺失值?
在下一节课中,你将看到如何进一步了解数据。
第四部分课:数据探索
数据科学的目标是从数据中讲述一个故事。让我们在这里看看一些示例。
在数据集中,有一列life_expectancy
。什么因素影响寿命?你可以做一些假设并通过数据验证。你可以检查世界不同地区的寿命是否存在差异:
print(df.groupby("region").mean(numeric_only=True)["life_expectancy"])
运行上述代码并观察其输出。存在一些差异,但并不十分剧烈。在 DataFrame 上应用groupby()
函数类似于 SQL 语句中的GROUP BY
子句。但是在 pandas 中,应用函数到groupby时需要注意列中的不同数据类型。如果像上面那样使用mean()
,它会计算所有列的均值(然后你选择了life_expectancy
),如果列不是数值型则会失败。因此,你需要添加一个参数来限制操作只针对那些列。
从上面可以看出,寿命与世界的哪个部分无关。你也可以按大洲分组,但这可能不太合适,因为某些大洲,如亚洲,既大又多样化。在这些情况下,平均值可能不具有参考价值。
你可以应用类似的操作来查找不是寿命而是人均 GDP。这是国家 GDP 除以人口,这是一种衡量国家富裕程度的指标。在代码中:
df["gdp_per_capita"] = df["gdp"] / df["population"]
print(df.groupby("region").mean(numeric_only=True)["gdp_per_capita"])
这显示了不同地区之间的巨大差异。因此,与预期寿命不同,你所在的地区与你的财富水平有关。
除了分组,探索和总结数据的另一个有用方法是数据透视表。pandas DataFrame 中有一个函数可以实现这一点。让我们看看不同地区对不同类型政府的偏好:
print(df.pivot_table(index="region", columns="democracy_type", aggfunc="count")["country"])
上表显示了计数,它作为汇总函数被指定。行(索引)是“区域”,列是democracy_type
中的值。每个单元格中的数字计数了该“民主类型”在同一“区域”中的实例。一些值是 NaN,这意味着该组合没有数据可以“计数”。由于这是计数,所以你知道它意味着零。
你的任务
数据透视表和分组是总结数据和提炼信息的非常强大的工具。你如何使用上述透视表来查找不同地区的人均 GDP 和民主类型的平均值?你会看到缺失值。为了帮助找出不同民主类型的平均值,合理的缺失值填补是什么?
在下一课中,你将学习如何从图表中调查数据。
第 05 课:可视化相关性
在上一课中,我们探讨了寿命预期和人均 GDP 列。它们有相关性吗?
有很多方法可以判断两个属性是否相关。散点图是一个很好的第一步,因为它提供了视觉证明。要将人均 GDP(如第 4 课中通过除以 GDP 和人口计算)与寿命预期绘制在一起,你可以使用 Python 库 Seaborn 结合 Matplotlib:
import seaborn as sns
sns.scatterplot(data=df, x="life_expectancy", y="gdp_per_capita", hue="continent")
上述散点图函数中的参数hue
是可选的。它根据另一个属性的值为点着色,因此,它对于说明例如非洲在寿命预期和人均 GDP 低端的表现很有用。
然而,上述图表存在一个问题:你无法看到任何线性模式,且很难判断两个属性之间的关系。在这种情况下,你必须转换数据以确定关系。让我们尝试使用半对数图,其中 y 轴以对数刻度呈现。你可以使用 Matplotlib 来调整刻度:
sns.scatterplot(data=df, x="life_expectancy", y="gdp_per_capita", hue="continent")
plt.yscale("log") # make y axis in log scale
现在,看起来寿命预期与人均 GDP 对数是线性的更有可能。
从数值上,你可以计算人均 GDP 对数和寿命预期之间的相关因子。相关因子接近 +1 或 -1 意味着相关性强。无相关的属性将显示接近零的相关因子。你可以使用 pandas 查找所有数值属性中相关性最强的因子。
top_features = df.corr(numeric_only=True)["life_expectancy"].abs().sort_values(ascending=False).index[:6]
print(top_features)
上述代码找出了与寿命预期最相关的前 6 个属性。无论是正相关还是负相关,因为排序是基于绝对值的。根据定义,寿命预期本身应该排在列表的最顶部,因为任何东西与自己具有相关性 1。
你可以使用 Seaborn 创建一个相关图,以显示任意一对属性之间的散点图:
sns.pairplot(df, vars=list(top_features))
plt.show()
相关图帮助你快速可视化相关性。例如,自雇百分比与脆弱就业百分比高度相关。出生率与预期寿命呈负相关(也许因为年龄越大,人们生育的可能性越小)。对角线上的直方图显示了该属性的分布情况。
你的任务
散点图是一个强大的工具,特别是当你有计算机来帮助你制作时。上面,你已经通过视觉展示了两个属性之间的相关性,但相关性不等于因果关系。要建立因果关系,你需要更多的证据。在统计学中,有九项在流行病学中非常著名的“布拉德福德·希尔标准”。一个更简单且较弱的表述是格兰杰因果关系的两个原则。查看你拥有的数据,并与格兰杰因果关系原则进行比较,证明预期寿命是由人均 GDP引起的需要哪些额外数据?
在下一课中,你将使用统计测试来分析你的数据。
课程 06:假设检验
由于数据科学的任务是讲述故事,因此支持你的主张是数据科学项目中的核心工作。
让我们再次关注预期寿命:城市化是提高预期寿命的关键,因为它还与先进的医学、卫生和免疫接种相关。你如何证明这一点?
一个简单的方法是展示两个预期寿命的直方图,一个是针对更多城市化国家的,另一个是针对非城市化国家的。让我们定义一个城市国家为城市人口超过 50%的国家。你可以使用 pandas 计算人口百分比,然后将数据集分为两个部分:
df["urban_pct"] = df["urban_population"]/(df["rural_population"] + df["urban_population"])
df_urban = df[df["urban_pct"] > 0.5]
df_rural = df[df["urban_pct"] <= 0.5]
然后,你可以创建一个重叠的直方图来显示预期寿命:
plt.hist(df_urban["life_expectancy"], alpha=0.7, bins=15, color="blue", label="Urba")
plt.hist(df_rural["life_expectancy"], alpha=0.7, bins=15, color="green", label="Rural")
plt.xlabel("Life expectancy")
plt.ylabel("Number of countries")
plt.legend(loc="upper left")
plt.tight_layout()
plt.show()
这证实了上述假设,即城市国家具有更高的预期寿命。然而,图表不是很有力的证据。更好的方法是应用一些统计测试来量化我们的主张的强度。你需要比较两个独立组之间的均值预期寿命,因此 t 检验是合适的。你可以使用 SciPy 包运行 t 检验,如下所示:
import scipy.stats as stats
df_urban = df[(df["urban_pct"] > 0.5) & df["life_expectancy"].notnull()]
df_rural = df[(df["urban_pct"] <= 0.5) & df["life_expectancy"].notnull()]
t_stat, p_value = stats.ttest_ind(df_urban["life_expectancy"], df_rural["life_expectancy"], equal_var=False)
print("t-Statistic:", t_stat)
print("p-value", p_value)
与 Matplotlib 不同,Matplotlib 会忽略缺失值,而 SciPy 在提供的数据中存在任何 NaN 时不会计算统计数据。因此,上面你通过移除缺失值来清理数据,并重新创建df_urban
和df_rural
数据框。t 检验提供了一个 1.6×10^(-10)的 p 值,这个值非常小。因此,零假设被拒绝,即拒绝两个组的均值相同。但这个 t 检验并没有告诉我们df_urban
或df_rural
的均值更高。你可以通过分别计算均值来轻松确定。
你的任务
与重新创建df_urban
和df_rural
数据框不同,你可以通过用各自的均值填补缺失值来使 SciPy 的 t 检验正常工作。尝试一下。这会改变 p 值吗?这改变了你的结论吗?
在下一课中,你将从数据中发现异常值。
课程 07:识别异常值
异常值是与大多数样本非常不同的样本,这使得它很难被视为更大群体的一部分。
识别异常值最著名的方法是正态分布的 68-95-99 规则,该规则指出距离均值一个、两个和三个标准差分别覆盖 68%、95%和 99%的样本。通常,一个距离均值 2 个标准差的样本被认为是足够远的异常值。我们来看看是否有哪个国家的预期寿命是异常值。
在使用 68-95-99 规则之前,你需要将数据转换得更接近正态分布。一个方法是使用 Box-Cox 变换。你可以通过比较变换前后的偏度来判断变换效果是否良好。完美的正态分布偏度为零:
boxcox_life, lmbda = stats.boxcox(df_rural["life_expectancy"])
boxcox_life = pd.Series(boxcox_life)
print(df_rural["life_expectancy"].skew(), boxcox_life.skew())
在 Box-Cox 变换后,偏度从 0.137 变化为-0.006,更接近于零。通过 Box-Cox 变换计算的 lambda 值在后续会很有用。顺便提一下,你可以验证变换后的数据大致对称:
plt.hist(boxcox_life, bins=15)
plt.show()
假设 Box-Cox 变换后的数据符合正态分布,我们可以很容易找到均值上下 2 个标准差的位置。但这只是变换后的数据。回忆一下 Box-Cox 变换是将y转换为 w=(y^λ – 1)/λ。因此,我们可以通过 (wλ + 1)^(1/λ) 进行反变换:
mean, stdev = boxcox_life.mean(), boxcox_life.std()
plus2sd = mean + 2 * stdev
minus2sd = mean - 2 * stdev
upperthreshold = (plus2sd * lmbda + 1)**(1/lmbda)
lowerthreshold = (minus2sd * lmbda + 1)**(1/lmbda)
print(lowerthreshold, upperthreshold)
这些是对于具有更多农村人口的国家来说,不是异常值的下界和上界。我们来看看是否有国家在这个范围之外:
print(df_rural[df_rural["life_expectancy"] <= lowerthreshold])
print(df_rural[df_rural["life_expectancy"] >= upperthreshold])
所以列支敦士登在上端是异常值,而乍得和莱索托在下端。这次测试只是指出了这些异常值,没有任何解释。你需要进一步研究数据,以假设为什么会出现这些情况。这是数据科学中的典型工作流程。
你的任务
你可以对df_urban
重复这个操作,找出哪些城市国家是异常值。在上下端有多少个国家是异常值?
这就是最后一课。
结束了!(看看你已经走了多远)
你做到了。做得好!
花一点时间回顾一下你已经取得的进展。
-
你发现了 pandas、missingno、scipy、seaborn 和 matplotlib 作为帮助你完成数据科学项目的 Python 库。
-
使用基本统计学,你可以从数据集中探索洞察。你也可以从数据中确认你的假设。
-
你了解了如何通过散点图等可视化工具以及统计测试来探索数据。
-
你知道数据变换如何帮助你从数据中提取信息,比如发现异常值。
不要小看这一点;你在短时间内取得了长足的进步。这只是你数据科学旅程的开始。继续练习并提升你的技能。
总结
你在这个迷你课程中表现如何?
你喜欢这个速成课程吗?
你有任何问题吗?有没有遇到什么难点?
告诉我。请在下方留言。
超越 SQL:使用 Pandas 将房地产数据转化为可操作的见解
在数据分析中,SQL 作为一个强大的工具,以其在管理和查询数据库方面的强大功能而闻名。Python 中的 pandas 库为数据科学家带来了类似 SQL 的功能,使其能够进行复杂的数据操作和分析,而无需传统的 SQL 数据库。在接下来的内容中,你将应用 Python 中的类似 SQL 的函数来剖析和理解数据。
超越 SQL:使用 Pandas 将房地产数据转化为可操作的见解
照片由Lukas W.提供,部分权利保留。
让我们开始吧。
概述
本文分为三个部分,它们是:
-
使用 Pandas 的
DataFrame.query()
方法探索数据 -
数据聚合与分组
-
精通 Pandas 中的行和列选择
-
利用数据透视表进行深入的房市分析
使用 Pandas 的DataFrame.query()
方法探索数据
pandas 中的DataFrame.query()
方法允许根据指定条件选择行,类似于 SQL 的SELECT
语句。从基础开始,你可以基于单个或多个条件过滤数据,从而为更复杂的数据查询奠定基础。
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# Load the dataset
Ames = pd.read_csv('Ames.csv')
# Simple querying: Select houses priced above $600,000
high_value_houses = Ames.query('SalePrice > 600000')
print(high_value_houses)
在上述代码中,你利用 pandas 中的DataFrame.query()
方法筛选出价格高于$600,000 的房屋,将结果存储在一个名为high_value_houses
的新 DataFrame 中。此方法允许基于作为字符串指定的条件对数据进行简洁易读的查询。在这种情况下,条件为'SalePrice > 600000'
。
下面的结果 DataFrame 展示了所选的高价值房产。查询有效地将数据集缩小到售价超过$600,000 的房屋,仅展示了 5 个符合该标准的房产。过滤后的视图提供了对 Ames 数据集中高价值房产的集中观察,提供了有关这些高价值房产的特征和位置的见解。
PID GrLivArea ... Latitude Longitude
65 528164060 2470 ... 42.058475 -93.656810
584 528150070 2364 ... 42.060462 -93.655516
1007 528351010 4316 ... 42.051982 -93.657450
1325 528320060 3627 ... 42.053228 -93.657649
1639 528110020 2674 ... 42.063049 -93.655918
[5 rows x 85 columns]
在下面的下一个示例中,让我们进一步探索DataFrame.query()
方法的功能,以根据更具体的标准过滤 Ames Housing 数据集。查询选择了卧室数量超过 3 间(BedroomAbvGr > 3
)且价格低于$300,000(SalePrice < 300000
)的房屋。此条件组合通过逻辑与操作符(&
)实现,使你能够同时应用多个过滤器到数据集中。
# Advanced querying: Select houses with more than 3 bedrooms and priced below $300,000
specific_houses = Ames.query('BedroomAbvGr > 3 & SalePrice < 300000')
print(specific_houses)
该查询的结果存储在一个新的 DataFrame 中,名为specific_houses
,其中包含满足两个条件的所有属性。通过打印specific_houses
,你可以检查既相对较大(就卧室而言)又负担得起的房屋的详细信息,目标是特定的住房市场细分,这可能会吸引那些寻找在特定预算范围内有宽敞居住选择的家庭。
PID GrLivArea ... Latitude Longitude
5 908128060 1922 ... 42.018988 -93.671572
23 902326030 2640 ... 42.029358 -93.612289
33 903400180 1848 ... 42.029544 -93.627377
38 527327050 2030 ... 42.054506 -93.631560
40 528326110 2172 ... 42.055785 -93.651102
... ... ... ... ... ...
2539 905101310 1768 ... 42.033393 -93.671295
2557 905107250 1440 ... 42.031349 -93.673578
2562 535101110 1584 ... 42.048256 -93.619860
2575 905402060 1733 ... 42.027669 -93.666138
2576 909275030 2002 ... NaN NaN
[352 rows x 85 columns]
高级查询成功识别出 Ames Housing 数据集中总计 352 套符合指定条件的房屋:有超过 3 个卧室且售价低于$300,000。这个属性子集突显了市场上的一个重要部分,提供宽敞的居住选择而不会超出预算,适合寻找经济实惠但宽敞住房的家庭或个人。为了进一步探讨这个子集的动态,让我们可视化销售价格与地面居住面积之间的关系,并增加一个额外的层次来指示卧室数量。这个图形表示将帮助你理解居住空间和卧室数量如何影响这些房屋在指定条件下的可负担性和吸引力。
# Visualizing the advanced query results
plt.figure(figsize=(10, 6))
sns.scatterplot(x='GrLivArea', y='SalePrice', hue='BedroomAbvGr', data=specific_houses, palette='viridis')
plt.title('Sales Price vs. Ground Living Area')
plt.xlabel('Ground Living Area (sqft)')
plt.ylabel('Sales Price ($)')
plt.legend(title='Bedrooms Above Ground')
plt.show()
散点图显示了销售价格与卧室数量和居住面积之间的分布
上面的散点图生动地展示了销售价格、居住面积和卧室数量之间的微妙关系,突出了 Ames 住房市场中这一细分市场的多样选择。它突显了较大的居住空间和额外卧室如何影响房产的价值,为关注宽敞且经济实惠住房的潜在买家和投资者提供了宝贵的见解。这个视觉分析不仅使数据更易于理解,还强调了 Pandas 在揭示关键市场趋势中的实际效用。
用我的书《数据科学入门指南》启动你的项目。它提供了自学教程和实用代码。
数据聚合与分组
聚合和分组在总结数据洞察中至关重要。在你探索的第一部分中建立在基础查询技术的基础上,让我们深入研究 Python 中数据聚合和分组的力量。类似于 SQL 的GROUP BY
子句,pandas 提供了一个强大的groupby()
方法,使你能够将数据分成子集以进行详细分析。在你旅程的下一个阶段,专注于利用这些功能揭示 Ames Housing 数据集中隐藏的模式和洞察。具体来说,你将检查在不同邻里中,超过三个卧室且售价低于$300,000 的房屋的平均售价。通过聚合这些数据,你旨在突出 Ames, Iowa 空间画布上住房可负担性和库存的变化。
# Advanced querying: Select houses with more than 3 bedrooms and priced below $300,000
specific_houses = Ames.query('BedroomAbvGr > 3 & SalePrice < 300000')
# Group by neighborhood, then calculate the average and total sale price, and count the houses
grouped_data = specific_houses.groupby('Neighborhood').agg({
'SalePrice': ['mean', 'count']
})
# Renaming the columns for clarity
grouped_data.columns = ['Average Sales Price', 'House Count']
# Round the average sale price to 2 decimal places
grouped_data['Averages Sales Price'] = grouped_data['Average Sales Price'].round(2)
print(grouped_data)
Average Sales Price House Count
Neighborhood
BrDale 113700.00 1
BrkSide 154840.00 10
ClearCr 206756.31 13
CollgCr 233504.17 12
Crawfor 199946.68 19
Edwards 142372.41 29
Gilbert 222554.74 19
IDOTRR 146953.85 13
MeadowV 135966.67 3
Mitchel 152030.77 13
NAmes 158835.59 59
NPkVill 143000.00 1
NWAmes 203846.28 39
NoRidge 272222.22 18
NridgHt 275000.00 3
OldTown 142586.72 43
SWISU 147493.33 15
Sawyer 148375.00 16
SawyerW 217952.06 16
Somerst 247333.33 3
StoneBr 270000.00 1
Timber 247652.17 6
通过使用 Seaborn 进行可视化,我们的目标是创建一个直观且易于访问的数据表示。你可以创建一个条形图,展示按社区划分的平均销售价格,并附上房屋数量的注释,以在一个连贯的图表中展示价格和数量。
# Ensure 'Neighborhood' is a column (reset index if it was the index)
grouped_data_reset = grouped_data.reset_index().sort_values(by='Average Sales Price')
# Set the aesthetic style of the plots
sns.set_theme(style="whitegrid")
# Create the bar plot
plt.figure(figsize=(12, 8))
barplot = sns.barplot(
x='Neighborhood',
y='Average Sales Price',
data=grouped_data_reset,
palette="coolwarm",
hue='Neighborhood',
legend=False,
errorbar=None # Removes the confidence interval bars
)
# Rotate the x-axis labels for better readability
plt.xticks(rotation=45)
# Annotate each bar with the house count, using enumerate to access the index for positioning
for index, value in enumerate(grouped_data_reset['Average Sales Price']):
house_count = grouped_data_reset.loc[index, 'House Count']
plt.text(index, value, f'{house_count}', ha='center', va='bottom')
plt.title('Average Sales Price by Neighborhood', fontsize=18)
plt.xlabel('Neighborhood')
plt.ylabel('Average Sales Price ($)')
plt.tight_layout() # Adjust the layout
plt.show()
按升序比较社区的平均销售价格
分析和随后的可视化强调了在艾姆斯(Ames),爱荷华州,符合特定标准(超过三间卧室且价格低于 $300,000)的房屋在可负担性和可获得性上的显著差异。这不仅展示了 SQL 类函数在 Python 中用于实际数据分析的实际应用,还提供了有关地方房地产市场动态的宝贵见解。
精通 Pandas 中的行和列选择
从 DataFrame 中选择特定的数据子集是常见的需求。你可以使用两个强大的方法:DataFrame.loc[]
和 DataFrame.iloc[]
。这两者的目的相似——选择数据——但它们在引用行和列时有所不同。
理解 DataFrame.loc[]
方法
DataFrame.loc[]
是一种基于标签的数据选择方法,这意味着你使用行和列的标签来选择数据。对于基于列名和行索引选择数据,它非常直观,尤其是当你知道感兴趣的具体标签时。
语法:DataFrame.loc[row_label, column_label]
目标:让我们选择所有超过 3 间卧室、价格低于 $300,000 的房屋,位于以高平均销售价格著称的特定社区(基于你之前的发现),并显示它们的 ‘Neighborhood’,‘SalePrice’ 和 ‘GrLivArea’。
# Assuming 'high_value_neighborhoods' is a list of neighborhoods with higher average sale prices
high_value_neighborhoods = ['NridgHt', 'NoRidge', 'StoneBr']
# Use df.loc[] to select houses based on your conditions and only in high-value neighborhoods
high_value_houses_specific = Ames.loc[(Ames['BedroomAbvGr'] > 3) &
(Ames['SalePrice'] < 300000) &
(Ames['Neighborhood'].isin(high_value_neighborhoods)),
['Neighborhood', 'SalePrice', 'GrLivArea']]
print(high_value_houses_specific.head())
Neighborhood SalePrice GrLivArea
40 NoRidge 291000 2172
162 NoRidge 285000 2225
460 NridgHt 250000 2088
468 NoRidge 268000 2295
490 NoRidge 260000 2417
理解 DataFrame.iloc[]
方法
相对而言,DataFrame.iloc[]
是一种基于整数位置的索引方法。这意味着你使用整数来指定要选择的行和列。它特别有用,以按位置访问 DataFrame 中的数据。
语法:DataFrame.iloc[row_position, column_position]
目标:接下来的重点是揭示艾姆斯数据集中不妥协于空间的经济实惠的住房选项,特别是寻找至少有 3 间以上的卧室且价格低于 $300,000 的房屋,排除高价值社区。
# Filter for houses not in the 'high_value_neighborhoods',
# with at least 3 bedrooms above grade, and priced below $300,000
low_value_spacious_houses = Ames.loc[(~Ames['Neighborhood'].isin(high_value_neighborhoods)) &
(Ames['BedroomAbvGr'] >= 3) &
(Ames['SalePrice'] < 300000)]
# Sort these houses by 'SalePrice' to highlight the lower end explicitly
low_value_spacious_houses_sorted = low_value_spacious_houses.sort_values(by='SalePrice').reset_index(drop=True)
# Using df.iloc to select and print the first 5 observations of such low-value houses
low_value_spacious_first_5 = low_value_spacious_houses_sorted.iloc[:5, :]
# Print only relevant columns to match the earlier high-value example: 'Neighborhood', 'SalePrice', 'GrLivArea'
print(low_value_spacious_first_5[['Neighborhood', 'SalePrice', 'GrLivArea']])
Neighborhood SalePrice GrLivArea
0 IDOTRR 40000 1317
1 IDOTRR 50000 1484
2 IDOTRR 55000 1092
3 Sawyer 62383 864
4 Edwards 63000 1112
在你探索DataFrame.loc[]
和DataFrame.iloc[]
时,你发现了 pandas 在行和列选择方面的能力,展示了这些方法在数据分析中的灵活性和强大功能。通过来自 Ames Housing 数据集的实际示例,你看到DataFrame.loc[]
允许基于标签进行直观的选择,适用于根据已知标签定位特定数据。相对而言,DataFrame.iloc[]
提供了一种通过整数位置精确访问数据的方法,提供了一种用于位置选择的基本工具,特别适用于需要关注数据片段或样本的场景。无论是在特定社区中筛选高价值物业,还是在更广泛的市场中识别入门级住房,掌握这些选择技巧都丰富了你的数据科学工具包,使数据探索更加有针对性和富有洞察力。
想要开始学习《数据科学初学者指南》吗?
现在就参加我的免费邮件速成课程吧(附带示例代码)。
点击注册,还可以免费获得课程的 PDF 电子书版本。
利用数据透视表进行深入的住房市场分析
当你深入探讨 Ames Housing 数据集时,你的分析之旅将引入 pandas 中数据透视表的强大功能。数据透视表作为一个宝贵的工具,可以总结、分析和呈现复杂数据,以易于消化的格式。这种技术允许你交叉汇总和分段数据,以揭示可能否则会被隐藏的模式和见解。在本节中,你将利用数据透视表更深入地剖析住房市场,重点关注社区特征、卧室数量和销售价格之间的相互作用。
为了为你的数据透视表分析做好准备,你将数据集筛选为价格低于 $300,000 且至少有一个高于地面的卧室。这个标准关注更实惠的住房选项,确保你的分析对更广泛的受众仍然相关。然后,你将构建一个数据透视表,按社区和卧室数量分段平均销售价格,旨在揭示影响 Ames 住房可负担性和偏好的模式。
# Import an additional library
import numpy as np
# Filter for houses priced below $300,000 and with at least 1 bedroom above grade
affordable_houses = Ames.query('SalePrice < 300000 & BedroomAbvGr > 0')
# Create a pivot table to analyze average sale price by neighborhood and number of bedrooms
pivot_table = affordable_houses.pivot_table(values='SalePrice',
index='Neighborhood',
columns='BedroomAbvGr',
aggfunc='mean').round(2)
# Fill missing values with 0 for better readability and to indicate no data for that segment
pivot_table = pivot_table.fillna(0)
# Adjust pandas display options to ensure all columns are shown
pd.set_option('display.max_columns', None)
print(pivot_table)
在我们讨论一些见解之前,先快速查看一下数据透视表。
BedroomAbvGr 1 2 3 4 5 6
Neighborhood
Blmngtn 178450.00 197931.19 0.00 0.00 0.00 0.00
Blueste 192500.00 128557.14 151000.00 0.00 0.00 0.00
BrDale 0.00 99700.00 111946.43 113700.00 0.00 0.00
BrkSide 77583.33 108007.89 140058.67 148211.11 214500.00 0.00
ClearCr 212250.00 220237.50 190136.36 209883.20 196333.33 0.00
CollgCr 154890.00 181650.00 196650.98 233504.17 0.00 0.00
Crawfor 289000.00 166345.00 193433.75 198763.94 210000.00 0.00
Edwards 59500.00 117286.27 134660.65 137332.00 191866.67 119900.00
Gilbert 0.00 172000.00 182178.30 223585.56 204000.00 0.00
Greens 193531.25 0.00 0.00 0.00 0.00 0.00
GrnHill 0.00 230000.00 0.00 0.00 0.00 0.00
IDOTRR 67378.00 93503.57 111681.13 144081.82 162750.00 0.00
Landmrk 0.00 0.00 137000.00 0.00 0.00 0.00
MeadowV 82128.57 105500.00 94382.00 128250.00 151400.00 0.00
Mitchel 176750.00 150366.67 168759.09 149581.82 165500.00 0.00
NAmes 139500.00 133098.93 146260.96 159065.22 180360.00 144062.50
NPkVill 0.00 134555.00 146163.64 143000.00 0.00 0.00
NWAmes 0.00 177765.00 183317.12 201165.00 253450.00 0.00
NoRidge 0.00 262000.00 259436.67 272222.22 0.00 0.00
NridgHt 211700.00 215458.55 264852.71 275000.00 0.00 0.00
OldTown 83333.33 105564.32 136843.57 136350.91 167050.00 97500.00
SWISU 60000.00 121044.44 132257.88 143444.44 158500.00 148633.33
Sawyer 185000.00 124694.23 138583.77 148884.62 0.00 146166.67
SawyerW 216000.00 156147.41 185192.14 211315.00 0.00 237863.25
Somerst 205216.67 191070.18 225570.39 247333.33 0.00 0.00
StoneBr 223966.67 211468.75 233750.00 270000.00 0.00 0.00
Timber 0.00 217263.64 200536.04 241202.60 279900.00 0.00
Veenker 247566.67 245150.00 214090.91 0.00 0.00 0.00
上述数据透视表提供了一个全面的快照,展示了不同卧室数量在各社区中如何影响平均销售价格。此分析揭示了几个关键见解:
-
各社区的可负担性:你可以一目了然地看到哪些社区提供了具有特定卧室数量的最实惠的住房选项,有助于有针对性地寻找住房。
-
卧室数量对价格的影响:该表格突出显示了卧室数量如何影响每个社区的销售价格,提供了对大房子的溢价的评估。
-
市场缺口和机会:零值区域表明缺乏符合特定标准的住房,这意味着市场上可能存在缺口或开发者和投资者的机会。
通过利用数据透视表进行分析,你成功地将 Ames 房地产市场中的复杂关系提炼为一种既易于访问又信息丰富的格式。这一过程不仅展示了 pandas 和类似 SQL 的分析技术之间的强大协同作用,还强调了先进数据处理工具在揭示房地产市场中可操作见解的重要性。尽管数据透视表非常有见地,但其真正的潜力是在与可视化分析相结合时发挥的。
为了进一步阐明你的发现并使其更具直观性,你将从数值分析过渡到可视化表示。热图是实现这一目的的优秀工具,特别是在处理像这样的多维数据时。然而,为了提高热图的清晰度并将注意力集中在可操作的数据上,你将使用自定义的颜色方案,以明确突出不存在的社区和卧室数量组合。
# Import an additional library
import matplotlib.colors
# Create a custom color map
cmap = matplotlib.colors.LinearSegmentedColormap.from_list("", ["red", "yellow", "green"])
# Mask for "zero" values to be colored with a different shade
mask = pivot_table == 0
# Set the size of the plot
plt.figure(figsize=(14, 10))
# Create a heatmap with the mask
sns.heatmap(pivot_table,
cmap=cmap,
annot=True,
fmt=".0f",
linewidths=.5,
mask=mask,
cbar_kws={'label': 'Average Sales Price ($)'})
# Adding title and labels for clarity
plt.title('Average Sales Price by Neighborhood and Number of Bedrooms', fontsize=16)
plt.xlabel('Number of Bedrooms Above Grade', fontsize=12)
plt.ylabel('Neighborhood', fontsize=12)
# Display the heatmap
plt.show()
显示按社区划分的平均销售价格的热图
热图生动地展示了不同社区中按卧室数量划分的平均销售价格的分布。这种颜色编码的视觉辅助工具使得哪些 Ames 地区为各种规模的家庭提供了最实惠的住房选择一目了然。此外,针对零值的独特阴影——表示不存在的社区和卧室数量组合——是市场分析中的一个关键工具。它突出了市场中可能存在需求但供应不足的缺口,为开发者和投资者提供了宝贵的见解。值得注意的是,你的分析还揭示了“旧城”社区的 6 间卧室的房屋价格低于$100,000。这一发现为大型家庭或寻找高卧室数量且价格合理的投资物业的投资者指明了优异的价值。
通过这一视觉探索,你不仅加深了对房地产市场动态的理解,还展示了高级数据可视化在房地产分析中的不可或缺的作用。数据透视表配合热图,展示了复杂的数据处理和可视化技术如何揭示房地产领域的有价值见解。
进一步阅读
本节提供了更多相关资源,如果你想深入了解,请参考。
Python 文档
资源
总结
通过对 Ames 住房数据集的全面探索,突显了 pandas 在进行复杂数据分析中的多功能性和强大能力,常常在不依赖传统数据库的环境中实现或超越 SQL 的可能性。从精准确定详细的住房市场趋势到识别独特的投资机会,你展示了一系列技术,使分析师具备了深度数据探索所需的工具。具体来说,你学会了如何:
-
利用
DataFrame.query()
进行数据选择,类似于 SQL 的SELECT
语句。 -
使用
DataFrame.groupby()
进行数据汇总和总结,类似于 SQL 的GROUP BY
。 -
应用高级数据处理技术,如
DataFrame.loc[]
、DataFrame.iloc[]
和DataFrame.pivot_table()
以进行更深入的分析。
有任何问题吗?请在下方评论中提出问题,我会尽力回答。
使用 LlamaIndex 构建简单的 RAG 应用程序
原文:
machinelearningmastery.com/building-a-simple-rag-application-using-llamaindex/
作者提供的图片
在本教程中,我们将深入探讨检索增强生成(RAG)和 LlamaIndex AI 框架。我们将学习如何使用 LlamaIndex 构建一个基于 RAG 的 Q&A 应用程序,该应用程序可以处理私有文档,并通过加入内存缓冲区来增强应用程序。这将使 LLM 能够使用文档和先前交互的上下文生成响应。
在 LLM 中什么是 RAG?
检索增强生成(RAG)是一种先进的方法,旨在通过将外部知识源整合到生成过程中来提高大语言模型(LLM)的性能。
RAG 涉及两个主要阶段:检索和内容生成。最初,从外部数据库中检索相关文档或数据,然后用于提供 LLM 的上下文,确保响应基于最当前和领域特定的信息。
什么是 LlamaIndex?
LlamaIndex 是一个先进的 AI 框架,旨在通过促进与多种数据源的无缝集成来增强大语言模型(LLM)的能力。它支持从超过 160 种不同格式的数据中检索数据,包括 API、PDF 和 SQL 数据库,使其在构建先进的 AI 应用程序时具有高度的灵活性。
我们甚至可以构建一个完整的多模态和多步骤 AI 应用程序,然后将其部署到服务器上,以提供高精度、特定领域的响应。与 LangChain 等其他框架相比,LlamaIndex 提供了一个更简单的解决方案,内置了适用于各种 LLM 应用程序的功能。
使用 LlamaIndex 构建 RAG 应用程序
在本节中,我们将构建一个 AI 应用程序,该应用程序从文件夹加载 Microsoft Word 文件,将它们转换为嵌入,将它们索引到向量存储中,并构建一个简单的查询引擎。之后,我们将使用向量存储作为检索器、LLM 和内存缓冲区,构建一个带有历史记录的 RAG 聊天机器人。
设置
安装所有必要的 Python 包,以加载数据和使用 OpenAI API。
!pip install llama-index
!pip install llama-index-embeddings-openai
!pip install llama-index-llms-openai
!pip install llama-index-readers-file
!pip install docx2txt
使用 OpenAI 函数初始化 LLM 和嵌入模型。我们将使用最新的“GPT-4o”和“text-embedding-3-small”模型。
from llama_index.llms.openai import OpenAI
from llama_index.embeddings.openai import OpenAIEmbedding
# initialize the LLM
llm = OpenAI(model="gpt-4o")
# initialize the embedding
embed_model = OpenAIEmbedding(model="text-embedding-3-small")
将 LLM 和嵌入模型都设置为全局,以便在调用需要 LLM 或嵌入的函数时,它将自动使用这些设置。
from llama_index.core import Settings
# global settings
Settings.llm = llm
Settings.embed_model = embed_model
加载和索引文档
从文件夹加载数据,将其转换为嵌入,并存储到向量存储中。
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
# load documents
data = SimpleDirectoryReader(input_dir="/work/data/",required_exts=[".docx"]).load_data()
# indexing documents using vector store
index = VectorStoreIndex.from_documents(data)
构建查询引擎
请将向量存储转换为查询引擎,并开始询问有关文档的问题。文档包括作者 Abid Ali Awan 于 6 月在 Machine Learning Mastery 发布的博客。
from llama_index.core <b>import</b> VectorStoreIndex
# converting vector store to query engine
query_engine = index.as_query_engine(similarity_top_k=3)
# generating query response
response = query_engine.query("What are the common themes of the blogs?")
print(response)
答案是准确的。
博客的共同主题围绕提升和技能在机器学习领域展开。它们专注于提供资源,例如免费的书籍、协作的平台,和数据集,以帮助个人深入了解机器学习算法,有效协作项目,并通过实际数据获得实践经验。这些资源旨在帮助初学者和专业人士建立坚实的基础和推动其在机器学习领域的职业发展。
使用记忆缓冲区构建 RAG 应用程序
之前的应用程序很简单;让我们创建一个更先进的聊天机器人,具有历史记录功能。
我们将使用检索器、聊天记忆缓冲区和 GPT-4o 模型来构建聊天机器人。
然后,我们将通过询问关于其中一篇博客文章的问题来测试我们的聊天机器人。
from llama_index.core.memory import ChatMemoryBuffer
from llama_index.core.chat_engine import CondensePlusContextChatEngine
# creating chat memory buffer
memory = ChatMemoryBuffer.from_defaults(token_limit=4500)
# creating chat engine
chat_engine = CondensePlusContextChatEngine.from_defaults(
index.as_retriever(),
memory=memory,
llm=llm
)
# generating chat response
response = chat_engine.chat(
"What is the one best course for mastering Reinforcement Learning?"
)
print(str(response))
它非常准确且切中要点。
根据提供的文档,Hugging Face 的“Deep RL 课程”是掌握强化学习的强烈推荐。该课程特别适合初学者和涵盖了强化学习的基础知识和高级技术。它包括诸如 Q-learning、深度 Q-learning、策略梯度、ML 代理、演员-评论家方法、多智能体系统和高级主题如 RLHF(从人类反馈中学习的强化学习)、决策变换器和MineRL。课程设计为一个月内完成,并提供实践实验,包括模型、提升分数的策略和一个跟踪进度的排行榜。
让我们提出后续问题,进一步了解课程内容。
response = chat_engine.chat(
"Tell me more about the course"
)
print(str(response))
如果你在运行上述代码时遇到问题,请参考 Deepnote 笔记本:使用 LlamaIndex 构建 RAG 应用程序。
结论
LlamaIndex 使得构建和部署 AI 应用程序变得简单。你只需写几行代码即可完成。
你学习旅程的下一步是使用 Gradio 构建一个合适的聊天机器人应用程序并将其部署到服务器上。为了进一步简化你的生活,你还可以查看 Llama Cloud。
在本教程中,我们了解了 LlamaIndex 以及如何构建一个 RAG 应用程序,以便从私人文档中提出问题。然后,我们构建了一个适当的 RAG 聊天机器人,该机器人使用私人文档和之前的聊天记录生成响应。
捕捉曲线:使用多项式回归进行高级建模
原文:
machinelearningmastery.com/capturing-curves-advanced-modeling-with-polynomial-regression/
当我们在机器学习中分析变量之间的关系时,我们常常发现直线无法全面描述情况。这时,多项式变换发挥作用,它为我们的回归模型添加了层次,同时不会使计算过程复杂化。通过将特征转换为它们的多项式对应物——平方、立方以及其他高阶项——我们赋予线性模型弯曲和扭曲的灵活性,从而更好地适应数据的潜在趋势。
本文将探讨如何超越简单的线性模型,以捕捉数据中的更复杂关系。你将了解多项式回归和立方回归技术的强大功能,这些技术使我们能够看到表面现象之外的潜在模式,这些模式可能会被直线忽略。我们还将深入讨论在模型中添加复杂性与保持预测能力之间的平衡,确保模型既强大又实用。
让我们开始吧。
捕捉曲线:使用多项式回归进行高级建模
图片由 Joakim Aglo 提供。保留所有权利。
概述
本文分为三个部分,它们是:
-
通过线性回归建立基准
-
使用多项式回归捕捉曲线
-
立方回归的实验
通过线性回归建立基准
当我们谈论两个变量之间的关系时,线性回归通常是第一步,因为它最简单。它通过将直线拟合到数据上来建模这种关系。这条直线由简单的方程 y = mx + b
描述,其中 y
是因变量,x
是自变量,m
是直线的斜率,b
是 y 轴截距。让我们通过预测 Ames 数据集中基于整体质量的“SalePrice”来演示这一点,整体质量是一个范围从 1 到 10 的整数值。
# Import the necessary libraries
import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import cross_val_score
import matplotlib.pyplot as plt
# Prepare data for linear regression
Ames = pd.read_csv("Ames.csv")
X = Ames[["OverallQual"]] # Predictor
y = Ames["SalePrice"] # Response
# Create and fit the linear regression model
linear_model = LinearRegression()
linear_model.fit(X, y)
# Coefficients
intercept = int(linear_model.intercept_)
slope = int(linear_model.coef_[0])
eqn = f"Fitted Line: y = {slope}x - {abs(intercept)}"
# Perform 5-fold cross-validation to evaluate model performance
cv_score = cross_val_score(linear_model, X, y).mean()
# Visualize Best Fit and display CV results
plt.figure(figsize=(10, 6))
plt.scatter(X, y, color="blue", alpha=0.5, label="Data points")
plt.plot(X, linear_model.predict(X), color="red", label=eqn)
plt.title("Linear Regression of SalePrice vs OverallQual", fontsize=16)
plt.xlabel("Overall Quality", fontsize=12)
plt.ylabel("Sale Price", fontsize=12)
plt.legend(fontsize=14)
plt.grid(True)
plt.text(1, 540000, f"5-Fold CV R²: {cv_score:.3f}", fontsize=14, color="green")
plt.show()
在基本线性回归中,我们的模型得出了以下方程:y = 43383x - 84264
。这意味着每增加一个质量点,与销售价格的增加约为 $43,383。为了评估模型的表现,我们使用了 5 折交叉验证,得出的 R² 值为 0.618。这个值表明,通过这个简单的模型,约 61.8% 的销售价格变异性可以通过房屋的整体质量来解释。
线性回归易于理解和实现。然而,它假设自变量和因变量之间的关系是线性的,但这可能并不总是如此,如上图的散点图所示。虽然线性回归提供了一个良好的起点,但现实世界的数据通常需要更复杂的模型来捕捉曲线关系,正如我们将在下一个关于多项式回归的部分中看到的那样。
使用多项式回归捕捉曲线
现实世界中的关系通常不是直线而是曲线。多项式回归允许我们建模这些曲线关系。对于三次多项式,这种方法将我们的简单线性方程扩展到每个x
的幂:y = ax + bx² + cx³ + d
。我们可以通过使用sklearn.preprocessing
库中的PolynomialFeatures
类来实现,它生成一个新的特征矩阵,包括所有小于或等于指定度数的特征的多项式组合。以下是我们如何将其应用于我们的数据集:
# Import the necessary libraries
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import PolynomialFeatures
import matplotlib.pyplot as plt
# Load the data
Ames = pd.read_csv("Ames.csv")
X = Ames[["OverallQual"]]
y = Ames["SalePrice"]
# Transform the predictor variable to polynomial features up to the 3rd degree
poly = PolynomialFeatures(degree=3, include_bias=False)
X_poly = poly.fit_transform(X)
# Create and fit the polynomial regression model
poly_model = LinearRegression()
poly_model.fit(X_poly, y)
# Extract model coefficients that form the polynomial equation
#intercept = np.rint(poly_model.intercept_).astype(int)
intercept = int(poly_model.intercept_)
coefs = np.rint(poly_model.coef_).astype(int)
eqn = f"Fitted Line: y = {coefs[0]}x¹ - {abs(coefs[1])}x² + {coefs[2]}x³ - {abs(intercept)}"
# Perform 5-fold cross-validation
cv_score = cross_val_score(poly_model, X_poly, y).mean()
# Generate data to plot curve
X_range = np.linspace(X.min(), X.max(), 100).reshape(-1, 1)
X_range_poly = poly.transform(X_range)
# Plot
plt.figure(figsize=(10, 6))
plt.scatter(X, y, color="blue", alpha=0.5, label="Data points")
plt.plot(X_range, poly_model.predict(X_range_poly), color="red", label=eqn)
plt.title("Polynomial Regression (3rd Degree) of SalePrice vs OverallQual", fontsize=16)
plt.xlabel("Overall Quality", fontsize=12)
plt.ylabel("Sale Price", fontsize=12)
plt.legend(fontsize=14)
plt.grid(True)
plt.text(1, 540000, f"5-Fold CV R²: {cv_score:.3f}", fontsize=14, color="green")
plt.show()
首先,我们将预测变量转换为最高三次的多项式特征。这一增强将我们的特征集从仅有的x
(整体质量)扩展到x, x², x³
(即,每个特征变为三个不同但相关的特征),使我们的线性模型能够拟合数据中的更复杂的曲线关系。然后,我们将这些转换后的数据拟合到线性回归模型中,以捕捉整体质量和销售价格之间的非线性关系。
我们的新模型的方程为y = 65966x¹ - 11619x² + 1006x³ - 31343
。该曲线比直线更贴合数据点,表明模型更优。我们的 5 折交叉验证给出了 0.681 的 R²值,相比我们的线性模型有所改进。这表明包括平方项和立方项有助于模型捕捉数据中的更多复杂性。多项式回归引入了拟合曲线的能力,但有时专注于特定的幂,例如立方项,可以揭示更深刻的见解,如我们在立方回归中将深入探讨的那样。
实验立方回归
有时,我们可能怀疑x
的特定幂尤为重要。在这种情况下,我们可以专注于该幂。立方回归是一种特殊情况,我们通过独立变量的立方来建模关系:y = ax³ + b
。为了有效地专注于这个幂,我们可以利用sklearn.preprocessing
库中的FunctionTransformer
类,它允许我们创建自定义转换器,将特定函数应用于数据。这种方法对于隔离和突出高阶项如x³
对响应变量的影响非常有用,提供了立方项如何单独解释数据变异性的清晰视图。
# Import the necessary libraries
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import FunctionTransformer
import matplotlib.pyplot as plt
# Load data
Ames = pd.read_csv("Ames.csv")
X = Ames[["OverallQual"]]
y = Ames["SalePrice"]
# Function to apply cubic transformation
def cubic_transformation(x):
return x ** 3
# Apply transformation
cubic_transformer = FunctionTransformer(cubic_transformation)
X_cubic = cubic_transformer.fit_transform(X)
# Fit model
cubic_model = LinearRegression()
cubic_model.fit(X_cubic, y)
# Get coefficients and intercept
intercept_cubic = int(cubic_model.intercept_)
coef_cubic = int(cubic_model.coef_[0])
eqn = f"Fitted Line: y = {coef_cubic}x³ + {intercept_cubic}"
# Cross-validation
cv_score_cubic = cross_val_score(cubic_model, X_cubic, y).mean()
# Generate data to plot curve
X_range = np.linspace(X.min(), X.max(), 300)
X_range_cubic = cubic_transformer.transform(X_range)
# Plot
plt.figure(figsize=(10, 6))
plt.scatter(X, y, color="blue", alpha=0.5, label="Data points")
plt.plot(X_range, cubic_model.predict(X_range_cubic), color="red", label=eqn)
plt.title("Cubic Regression of SalePrice vs OverallQual", fontsize=16)
plt.xlabel("Overall Quality", fontsize=12)
plt.ylabel("Sale Price", fontsize=12)
plt.legend(fontsize=14)
plt.grid(True)
plt.text(1, 540000, f"5-Fold CV R²: {cv_score_cubic:.3f}", fontsize=14, color="green")
plt.show()
我们对自变量进行了立方变换,得到了立方模型,其方程为y = 361x³ + 85579
。这比完整的多项式回归模型稍简单,专注于立方项的预测能力。
使用立方回归,我们的 5 折交叉验证得到了 0.678 的 R²。这一表现略低于完整的多项式模型,但仍显著优于线性模型。立方回归比更高阶的多项式回归更简单,并且在某些数据集中足以捕捉关系。它比高阶多项式模型更不容易过拟合,但比线性模型更灵活。立方回归模型中的系数 361,表示随着质量立方的增加,销售价格的增长率。这强调了非常高质量水平对价格的重大影响,表明具有卓越质量的物业,其销售价格的增长幅度不成比例。这一见解对关注高端物业的投资者或开发商尤其有价值。
正如你可能想象的,这种技术并不限制于多项式回归。如果你认为在特定场景下有意义,你可以引入更复杂的函数,如对数函数和指数函数。
进一步阅读
API
教程
- 使用 scikit-learn 进行 Python 多项式回归 作者:Tamas Ujhelyi
Ames 房价数据集与数据字典
总结
本文探讨了适用于不同复杂度数据建模的各种回归技术。我们从线性回归开始,以建立预测房价的基线,基于质量评分。配套的视觉图示展示了线性模型如何试图通过数据点拟合一条直线,阐明了回归的基本概念。进一步使用多项式回归,我们处理了更复杂的非线性趋势,这提高了模型的灵活性和准确性。配套图表显示了多项式曲线如何比简单的线性模型更紧密地拟合数据点。最后,我们聚焦于立方回归,以检验预测变量特定幂次的影响,隔离高阶项对因变量的影响。立方模型被证明特别有效,以足够的精度和简单性捕捉了关系的基本特征。
具体而言,你学习了:
-
如何使用可视化技术识别非线性趋势。
-
如何使用多项式回归技术建模非线性趋势。
-
如何通过较少的模型复杂度来捕捉类似的预测性。
你有什么问题吗?请在下面的评论中提出问题,我会尽力回答。
车库与否?通过卡方检验获取爱荷华州艾姆斯市的住房见解
卡方独立性检验是一种统计程序,用于评估两个分类变量之间的关系——确定它们是相关的还是独立的。探索房产的视觉吸引力及其对估值的影响是很有趣的。但是你多久将房子的外观与车库等功能特征联系在一起?通过卡方检验,你可以确定这些特征之间是否存在统计学上显著的关联。
让我们开始吧。
车库与否?通过卡方检验获取爱荷华州艾姆斯市的住房见解
图片由Damir Kopezhanov提供。一些权利保留。
概述
本文分为四部分,它们是:
-
理解卡方检验
-
卡方检验的工作原理
-
揭示外部质量与车库存在之间的关系
-
重要注意事项
理解卡方检验
卡方( χ 2 \chi² χ2)检验之所以有用,是因为它能够测试分类变量之间的关系。它在处理名义或顺序数据时特别有价值,因为这些数据被划分为类别或组。卡方检验的主要目的是确定两个分类变量之间是否存在统计学上显著的关联。换句话说,它有助于回答以下问题:
-
两个分类变量是否相互独立?
- 如果变量是独立的,一个变量的变化与另一个变量的变化无关。它们之间没有关联。
-
两个分类变量之间是否存在显著关联?
- 如果变量之间存在关联,一个变量的变化与另一个变量的变化相关。卡方检验有助于量化这种关联是否具有统计学意义。
在你的研究中,你关注房子的外部质量(分为“优秀”或“一般”)及其与车库有无的关系。为了使卡方检验的结果有效,必须满足以下条件:
-
独立性: 观察值必须是独立的,意味着一个结果的发生不应影响另一个结果。我们的数据集符合这一点,因为每个条目代表一个独立的房子。
-
样本大小: 数据集不仅要随机抽样,而且要足够大以具代表性。我们的数据来自爱荷华州艾姆斯市,符合这一标准。
-
期望频率: 每个列联表中的单元格应该有至少 5 的期望频率。这对于检验的可靠性至关重要,因为卡方检验依赖于大样本近似。你将通过创建和可视化期望频率来展示这一条件。
启动你的项目,参考我的书籍数据科学入门指南。它提供了自学教程和可运行的代码。
卡方检验的工作原理
卡方检验将数据中的观察频率与假设中的期望频率进行比较。
卡方检验通过将列联表中类别的观察频率与在独立假设下预期的频率进行比较来工作。列联表是两个分类变量的交叉表,显示每个类别组合中有多少观察值。
-
零假设 ( H 0 H_0 H0): 卡方检验中的零假设假定两个变量之间独立,即观察到的频率(有或没有车库)应该匹配。
-
备择假设 ( H 1 H_1 H1): 备择假设表明两个变量之间存在显著关联,即观察到的频率(有或没有车库)应该根据另一个变量的值(房屋质量)有所不同。
卡方检验中的检验统计量通过比较列联表中每个单元格的观察频率和期望频率来计算。观察频率与期望频率之间的差异越大,卡方统计量越大。卡方检验产生一个 p 值,表示在独立假设下观察到观察到的关联(或更极端的关联)的概率。如果 p 值低于选择的显著性水平 α \alpha α(通常为 0.05),则拒绝独立性零假设,表明存在显著的关联。
揭示外部质量与车库存在之间的关联
使用Ames 房屋数据集,你着手确定房屋的外部质量与车库存在或不存在之间是否存在关联。让我们深入分析的细节,并辅以相应的 Python 代码。
# Importing the essential libraries
import pandas as pd
from scipy.stats import chi2_contingency
# Load the dataset
Ames = pd.read_csv('Ames.csv')
# Extracting the relevant columns
exterqual_garagefinish_data = Ames[['ExterQual', 'GarageFinish']].copy()
# Filling missing values in the 'GarageFinish' column with 'No Garage'
exterqual_garagefinish_data['GarageFinish'].fillna('No Garage', inplace=True)
# Grouping 'GarageFinish' into 'With Garage' and 'No Garage'
exterqual_garagefinish_data['Garage Group'] \
= exterqual_garagefinish_data['GarageFinish'] \
.apply(lambda x: 'With Garage' if x != 'No Garage' else 'No Garage')
# Grouping 'ExterQual' into 'Great' and 'Average'
exterqual_garagefinish_data['Quality Group'] \
= exterqual_garagefinish_data['ExterQual'] \
.apply(lambda x: 'Great' if x in ['Ex', 'Gd'] else 'Average')
# Constructing the simplified contingency table
simplified_contingency_table \
= pd.crosstab(exterqual_garagefinish_data['Quality Group'],
exterqual_garagefinish_data['Garage Group'])
#Printing the Observed Frequency
print("Observed Frequencies:")
observed_df = pd.DataFrame(simplified_contingency_table,
index=["Average", "Great"],
columns=["No Garage", "With Garage"])
print(observed_df)
print()
# Performing the Chi-squared test
chi2_stat, p_value, _, expected_freq = chi2_contingency(simplified_contingency_table)
# Printing the Expected Frequencies
print("Expected Frequencies:")
print(pd.DataFrame(expected_freq,
index=["Average", "Great"],
columns=["No Garage", "With Garage"]).round(1))
print()
# Printing the results of the test
print(f"Chi-squared Statistic: {chi2_stat:.4f}")
print(f"p-value: {p_value:.4e}")
输出应为:
Observed Frequencies:
No Garage With Garage
Average 121 1544
Great 8 906
Expected Frequencies:
No Garage With Garage
Average 83.3 1581.7
Great 45.7 868.3
Chi-squared Statistic: 49.4012
p-value: 2.0862e-12
上述代码执行了三个步骤:
数据加载与准备:
-
你首先加载了数据集,并提取了相关列:
ExterQual
(外部质量)和GarageFinish
(车库完成情况)。 -
识别到
GarageFinish
中的缺失值后,你明智地用标签"No Garage"
填补这些缺失值,表示没有车库的房屋。
简化的数据分组:
-
你进一步将
GarageFinish
数据分类为两组:“有车库”(对于任何类型的有车库的房屋)和“无车库”。 -
同样,你将
ExterQual
数据分为“优秀”(具有优秀或良好外部质量的房屋)和“一般”(具有平均或一般外部质量的房屋)两组。
卡方检验:
-
将数据适当准备后,你构建了一个列联表来展示新形成类别之间的观察频率。它们是输出中打印的两个表格。
-
然后,你使用 SciPy 对这个列联表执行了卡方检验。p 值被打印出来,发现远小于 α \alpha α。从测试中获得的极低 p 值表明,在这个数据集中,房屋外部质量与车库存在之间存在显著的统计关联。
-
仔细观察期望频率可以满足卡方检验的第三个条件,即每个单元格至少需要 5 次发生。
通过这项分析,你不仅使数据更加精炼和简化,使其更易解释,还提供了关于两个感兴趣的分类变量之间关联的统计证据。
想要开始学习数据科学初学者指南吗?
现在就参加我的免费电子邮件快速课程(带有示例代码)。
点击注册,并且还可以获得课程的免费 PDF 电子书版本。
重要注意事项
尽管卡方检验非常实用,但也有其局限性:
-
非因果关系: 虽然测试可以确定关联,但不能推断因果关系。因此,即使房屋外部质量与其车库存在之间存在显著联系,也不能得出一个导致另一个的结论。
-
方向性: 这项测试表明了一种关联,但并未指明其方向。然而,我们的数据表明,在外部质量“优秀”的房屋中更有可能有车库,而在“一般”标记的房屋中则可能性较小。
-
幅度: 该测试不提供关系强度的见解。其他度量指标,如克拉默 V,对此更具信息性。
-
外部效度: 我们的结论仅适用于 Ames 数据集。在将这些发现推广到其他地区时需谨慎。
进一步阅读
线上
资源
总结
在这篇文章中,你深入探讨了卡方检验及其在 Ames 住房数据集上的应用。你发现了房屋外部质量与车库存在之间的显著关联。
具体来说,你学到了:
-
卡方检验的基本原理和实际应用。
-
卡方检验揭示了 Ames 数据集中房屋外部质量与车库存在之间的显著关联。与“普通”评级的房屋相比,具有“优秀”外部质量评级的房屋更有可能拥有车库,这一趋势具有统计学意义。
-
卡方检验的重要警示和局限性。
你有任何问题吗?请在下面的评论中提问,我会尽力回答。