Python数据分析与程序设计(六):综合应用

前言

在上一篇关于Python数据分析与程序设计的文章中,我们专注于Pandas库的数据分析实践。通过Pandas,我们掌握了数据加载、清洗、探索和可视化等关键技能,这些都是数据分析的核心步骤。我们通过实例了解了如何使用DataFrame和Series进行数据操作,以及如何进行时间序列分析。

在本篇我们将更进一步,结合NumPy和matplotlib(plt)这两个强大的库,以扩展我们的数据分析能力。NumPy将为我们的数据处理和数值计算提供支持,而matplotlib将帮助我们通过图表更直观地展示数据。

接下来,我们将通过实际案例,展示如何综合运用Pandas、NumPy和matplotlib进行数据分析,以及如何通过图表更有效地传达分析结果。让我们开始这次数据分析的综合应用之旅吧!

数据集介绍

Amazon.com,Inc.是一家位于西雅图的美国跨国技术公司,专注于电子商务,云计算,数字流和人工智能。与Google,Apple和Facebook一起,它被认为是四大技术公司之一。

这个数据集包含了亚马逊公司(Amazon)自1997年至2020年的股票交易信息。数据以CSV(逗号分隔值)格式组织,涵盖了每天的开盘价(Open)、最高价(High)、最低价(Low)和收盘价(Close),以及相应的成交量(Volume)和股票的调整后收盘价(Adj Close)。这些数据可以用来分析亚马逊公司在这段时间内的股票表现和市场趋势。下面将使用恰当的python库对其进行数据探索分析:

导入相应包和模块

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用支持中文的字体,如 'SimHei'
plt.rcParams['axes.unicode_minus'] = False  # 正确显示负号

导入股票时间序列数据

导入股票数据,同时将列名设置为中文

df = pd.read_csv('C:\python_code\Data Analysis\Amazon.csv',names=['日期',\
'开盘价','最高价','最低价','收盘价','调整后收盘价','成交量'])

获取数据基本元属性信息,如,数据记录条数、属性类型等;

对于DataFrame来说,数据基本元信息通常包括以下几个方面:

  • 列名(Column Names):DataFrame中每一列的名称。这些名称通常在DataFrame的创建时就被定义,并且可以通过df.columns属性来访问。
  • 数据类型(Data Types):DataFrame中每一列的数据类型。这包括整数、浮点数、字符串、日期时间等。可以通过df.dtypes属性来获取每一列的数据类型。
  • 形状(Shape):DataFrame的形状,即它的行数和列数。可以通过df.shape属性来获取,返回一个元组(行数, 列数)。
  • 索引(Index):DataFrame的行索引。索引用于标识每一行,并且可以通过df.index属性来访问。
  • 描述性统计(Descriptive Statistics):DataFrame的描述性统计信息,如均值、标准差、最小值、最大值等。可以通过df.describe()方法来获取。
  • 非空值计数(Non-null Value Count):DataFrame中每一列非空(或者说有效)值的数量。可以通过df.count()方法来获取。
  • 唯一值(Unique Values):DataFrame中每一列的唯一值列表。可以通过df.nunique()方法来获取每一列的唯一值计数,或者使用df.apply(lambda x: x.unique())来获取每一列的唯一值数组。
  • 缺失值(Missing Values):DataFrame中每一列的缺失值(NaN或None)数量。可以通过df.isnull().sum()方法来获取。
  • 信息(Information):DataFrame的简要信息,包括每列的数据类型、非空值计数和内存使用情况。可以通过df.info()方法来获取。
  • 头部和尾部数据(Head and Tail Data):DataFrame的前几行和后几行数据。可以通过df.head(n)和df.tail(n)方法来获取,其中n是您希望查看的行数。
df = pd.read_csv('C:\python_code\Data Analysis\Amazon.csv',names=['日期','开盘价',\
'最高价','最低价','收盘价','调整后收盘价','成交量'])
print(df.head())
df = df.drop(0) # 发现第一行数据为 data open... 直接删除处理
print('stock的基本元信息\n')
print(f'columns:{df.columns}\n') # 确认转换成中文列索引
print(f'dtype:{df.dtypes}\n') # 反应出还需将数据值转换成对应类型 便于后续处理
print(df.info()) # 可以反应dataframe的简要信息

输出结果为:

stock的基本元信息

columns:Index(['日期', '开盘价', '最高价', '最低价', '收盘价', '调整后收盘价', '成交量'], dtype='object')

dtype:日期        object
开盘价       object
最高价       object
最低价       object
收盘价       object
调整后收盘价    object
成交量       object
dtype: object

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5842 entries, 1 to 5842
Data columns (total 7 columns):
 #   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
 0   日期      5842 non-null   object
 1   开盘价     5842 non-null   object
 2   最高价     5842 non-null   object
 3   最低价     5842 non-null   object
 4   收盘价     5842 non-null   object
 5   调整后收盘价  5842 non-null   object
 6   成交量     5842 non-null   object
dtypes: object(7)
memory usage: 319.6+ KB
None

数据预处理

对数据的缺失值进行检测,若存在缺失值,使用均值进行填补;

print(df.isnull().any())  # 检查每列是否有缺失值
print(df.isnull().sum())   # 获取每列的缺失值数量

输出结果为:

日期        False
开盘价       False
最高价       False
最低价       False
收盘价       False
调整后收盘价    False
成交量       False
dtype: bool
日期        0
开盘价       0
最高价       0
最低价       0
收盘价       0
调整后收盘价    0
成交量       0
dtype: int64

发现数据并不存在缺失值。

但如果存在缺失值,可以使用均值填补空缺,具体操作如下:

# 将所有列转换为数值型,无法转换的值将变为NaN
df_numeric = df.apply(pd.to_numeric, errors='coerce')
# print(df_numeric)

# 删除包含NaN的列,即无法转换为数值型的列
df_numeric_clean = df_numeric.dropna(how='any', axis=1)
# print(df_numeric_clean)

# 计算数值型列的均值
means = df_numeric_clean.mean()
# print(means)

# 使用均值填充缺失值
df_numeric_clean_filled = df_numeric_clean.fillna(means)
以下是errors参数的几个常见用法:

'raise': 默认设置。如果遇到无法转换为数字的数据,将抛出一个错误。

'ignore': 忽略无法转换为数字的数据,保持原样。

'coerce': 将无法转换为数字的数据设置为NaN(不是数字)。这是处理混合数据类型时的一个有用选项,因为它允许转换过程继续进行,而不中断整个操作。
在Pandas中,dropna方法用于删除含有缺失值(NaN)的数据。
参数how决定了删除行为的规则,以下是how参数的几种用法:

'any': 这是默认设置。如果轴(由axis参数指定)上的存在值是NaN

'all': 只有当一整行或一整列的所有值都是NaN时,该行或列才会被删除。

参数axis指定了操作的轴向,即沿着哪个方向进行操作:

axis=0 或 axis='index':操作沿着行的方向,即删除列。
axis=1 或 axis='columns':操作沿着列的方向,即删除行。
当您在某些环境中运行代码时,
如果输出结果非常大,可能会超出显示限制。
在这种情况下,通常会看到一条消息提示
“Output exceeds the size limit. Open the full output data in a text editor”。
这意味着您需要在文本编辑器中打开输出,以便查看完整的数据。

以下是一些处理这种情况的建议:

导出数据:如果您正在处理一个大型的DataFrame或数据集,并且只需要查看或分析其中的一部分,
可以考虑将数据导出到文件中,例如CSV或Excel文件。
例如,使用df.to_csv('output.csv')或df.to_excel('output.xlsx')

使用箱线图,对数据中的异常值进行检测,若存在异常值,使用中位数进行替换;

# DataFrame已经被清洗并填充了缺失值
# 首先,选择DataFrame中的数值型列
numeric_cols = df_numeric_clean_filled.select_dtypes(include=[np.number]).columns.tolist()
# 然后,为每个数值型列绘制箱线图
for col in numeric_cols:
    plt.boxplot(df_numeric_clean_filled[col])
    plt.show()
df_numeric_clean_filled 是一个Pandas DataFrame,它假定已经被填充或清洗过,可能已经没有缺失值(NaN)。

.select_dtypes(include=[np.number]) 是一个Pandas方法,用于基于数据类型选择列。include=[np.number] 参数告诉方法只选择数据类型为数值型(整数或浮点数)的列。

.columns 属性返回被 .select_dtypes() 方法选中的列的名称。

.tolist() 将列名从Pandas的Index对象转换为Python的列表。

可以发现对于每一个列来说,都出现了大量的异常值,这是因为股票数据具有强烈的时间序列特性,即数据点之间存在顺序和依赖关系。箱线图通常用于展示静态数据集的分布情况,而不考虑数据点之间的时间顺序。这可能导致对股票价格趋势和周期性模式的误解。

因此,在分析股票数据时,虽然箱线图可以提供一些有用的信息,但也应结合实际情况,才能更全面和合理的实现市场洞察;同时我们可以粗略的认为:对于股票这类数据是不存在上下限的限制,箱线图的上下限只是主观经验的参考;同时观察箱线图发现数据中并不存在负的异常值,所以我们认为数据合理。

同时对于一些适合使用箱线图分析的数据集若存在异常值,使用中位数进行替换,具体操作如下:

# 计算IQR
Q1 = df_numeric_clean_filled.quantile(0.25)
Q3 = df_numeric_clean_filled.quantile(0.75)
IQR = Q3 - Q1

# 计算异常值的上下界
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
print(lower_bound)
print(upper_bound)
# 替换异常值为中位数
median = df_numeric_clean_filled.median()
for column in df_numeric_clean_filled.columns:
    # 将下界和上界之外的值替换为中位数
    df_numeric_clean_filled[column] = df_numeric_clean_filled[column].apply(lambda x: median[column] if x < lower_bound[column] or x > upper_bound[column] else x)
df_numeric_clean_filled.boxplot()  # 再次绘制所有列的箱线图观察
plt.show()

使用适当的编码方法,将数据中的非数值型字段替换为数值型;

此步骤在上文已具体实现,相关代码如下:

# 将所有列转换为数值型,无法转换的值将变为NaN
df_numeric = df.apply(pd.to_numeric, errors='coerce')
# print(df_numeric)

增加新列“one_volume”,实现对原 volume列的归一化处理。

column_to_normalize = '成交量'
min_value = df_numeric_clean_filled[column_to_normalize].min()
max_value = df_numeric_clean_filled[column_to_normalize].max()   
# 进行归一化处理
df_numeric_clean_filled['归一化成交量'] = (df_numeric_clean_filled[column_to_normalize] - min_value) / (max_value - min_value)
print(df_numeric_clean_filled['归一化成交量'])

绘图


绘制股票成交量的时间序列图

简单理解,即为 时间为横坐标 成交量为纵坐标

预处理操作:

# 转成datetime类型
df_numeric_clean_filled['日期'] = pd.to_datetime(df_numeric_clean_filled['日期'])
# 将日期列设置为索引
df_set_index_data = df_numeric_clean_filled.set_index('日期')

全量数据

plt.plot(df_numeric_clean_filled['日期'],df_numeric_clean_filled['成交量'],label='成交量')

# plt.plot(df_set_index_data.index,df_set_index_data['成交量'])
plt.xlabel("日期", fontsize=15)  # 设置X轴标签
plt.ylabel("成交量", fontsize=15)  # 设置Y轴标签
plt.title('股票成交量的时间序列图--全量数据')
plt.legend()
plt.show()

年数据

# 以年为单位对数据进行重采样,并计算每年的成交量总和
# 这里使用'sum'作为重采样的聚合函数,也可以使用其他函数如'mean'等
df_annual = df_set_index_data.resample('YE')['成交量'].sum()
# resample('YE'):这个方法对 DataFrame 进行重采样,将数据按照年度('YE' 表示年度结束,即每个年底)进行分组。如果数据是按日度记录的,这个方法会将每一年的记录合并到一个单独的组中。重采样后,新的索引将是每年的最后一天。
# ['成交量'].sum():这部分代码选择了 '成交量' 列,并计算了每个重采样周期(在这个例子中是每年)的总和。sum() 是一个聚合函数,它会对每个分组的数据进行求和操作。
print(type(df_annual)) # 此时是一个系列
# df_annual.plot()
# plt.show()

plt.plot(df_annual,label='成交量')
plt.xlabel("日期", fontsize=15)  # 设置X轴标签
plt.ylabel("成交量", fontsize=15)  # 设置Y轴标签
plt.title('股票成交量的时间序列图--年数据')
plt.legend()
plt.show()

月数据(此处演示每年七月)

# 每年的x月份
df_annual_july = df_set_index_data.resample('YE-JUL')['成交量'].sum()  # 每年的7月份

plt.plot(df_annual,label='成交量')
plt.xlabel("日期", fontsize=15)  # 设置X轴标签
plt.ylabel("成交量", fontsize=15)  # 设置Y轴标签
plt.title('股票成交量的时间序列图--每年七月数据')
plt.legend()
plt.show()

绘制股票收盘价和成交量的时间序列图(提示:如果数值差异很大,考虑采用两套纵坐标系来做图)

全年数据

# 绘制收盘价
fig,ax1 = plt.subplots(figsize=(11, 7))
# 绘制第一组数据
ax1.plot(df_set_index_data['收盘价'],color='blue',label='收盘价')
ax1.set_ylabel("收盘价", fontsize=15)  # 设置Y轴标签

# 创建第二个y轴对象,共享x轴
ax2 = ax1.twinx()
ax2.plot(df_set_index_data['成交量'],color='red',label='成交量')
ax2.set_ylabel("成交量",fontsize=15) # 设置Y轴标签
ax1.set_xlabel("日期", fontsize=15)  # 设置X轴标签
ax1.set_title('股票成交量的时间序列图--全量数据')
ax1.legend()
ax2.legend()
plt.show()
fig, ax1 = plt.subplots(figsize=(11, 7)):创建一个新的图形(fig)和一个子图轴(ax1),figsize=(11, 7) 设置了图形的大小。

ax1.plot(df_set_index_data['收盘价'], color='blue', label='收盘价'):在 ax1 上绘制收盘价数据,使用蓝色线条,并设置图例标签为“收盘价”。

ax1.set_ylabel("收盘价", fontsize=15):设置 ax1 的 y 轴标签为“收盘价”,并设置字体大小为 15。

ax2 = ax1.twinx():创建第二个 y 轴对象 ax2,它与 ax1 共享 x 轴,但拥有独立的 y 轴刻度和标签,这允许在同一图表中展示两种不同的量度,且两者的 y 轴刻度互不影响。

ax2.plot(df_set_index_data['成交量'], color='red', label='成交量'):在 ax2 上绘制成交量数据,使用红色线条,并设置图例标签为“成交量”。

ax2.set_ylabel("成交量", fontsize=15):设置 ax2 的 y 轴标签为“成交量”,并设置字体大小为 15。

ax1.set_xlabel("日期", fontsize=15):设置两个轴共享的 x 轴标签为“日期”,并设置字体大小为 15。

ax1.set_title('股票成交量的时间序列图--全量数据'):设置整个图形的标题。

ax1.legend() 和 ax2.legend():分别为 ax1 和 ax2 显示图例。

plt.show():显示图形。

年数据

# 处理数据-年数据
df_annual_close = df_set_index_data.resample('YE')['收盘价'].sum() # 返回的是一个系列
df_annual_volume = df_set_index_data.resample('YE')['成交量'].sum()

# 创建一个新的图形和子图对象,设置图形大小为宽10英寸、高6英寸
fig, ax1 = plt.subplots(figsize=(10, 6))
# 绘制第一组数据
ax1.plot(df_annual_close,color='blue',label='收盘价')
ax1.set_ylabel("收盘价", fontsize=15)  # 设置Y轴标签
# 创建第二个y轴对象,共享x轴
ax2 = ax1.twinx()
ax2.plot(df_annual_volume,color='red',label='成交量')
ax2.set_ylabel("成交量",fontsize=15) # 设置Y轴标签
ax1.set_xlabel("日期", fontsize=15)  # 设置X轴标签
ax1.set_title('股票成交量的时间序列图--年数据')
ax2.legend()
ax1.legend()
plt.show()

月数据(选择每年七月)

# 处理数据-每年的x月份
df_annual_july_close = df_set_index_data.resample('YE-JUL')['收盘价'].sum() # 返回的是一个系列
df_annual_july_volume = df_set_index_data.resample('YE-JUL')['成交量'].sum()

# 创建一个新的图形和子图对象,设置图形大小为宽10英寸、高6英寸
fig, ax1 = plt.subplots(figsize=(10, 6))
# 绘制第一组数据
ax1.plot(df_annual_july_close,color='blue',label='收盘价')
ax1.set_ylabel("收盘价", fontsize=15)  # 设置Y轴标签
# 创建第二个y轴对象,共享x轴
ax2 = ax1.twinx()
ax2.plot(df_annual_july_volume,color='red',label='成交量')
ax2.set_ylabel("成交量",fontsize=15) # 设置Y轴标签
ax1.set_xlabel("日期", fontsize=15)  # 设置X轴标签
ax1.set_title('股票成交量的时间序列图--每年七月数据')
ax2.legend()
ax1.legend()
plt.show()

绘制K线图

k线图能够全面透彻地观察到市场的真正变化。我们从K线图中,既可看到股价(或大市)的趋势,也同时可以了解到每日市况的波动情形。

安装mpl_finance模块(pip install mpl_finance),使用mpl_finance模块中的candlestick_ohIc()函数绘制K线图。

import mpl_finance as mpf
import matplotlib.dates as dates
 
df_1 = pd.read_csv('Amazon.csv')
df_1['Date'] = pd.to_datetime(df_1['Date'])

df_1.set_index('Date',inplace=True)
new_df = df_1.loc['2000-1':'2000-12',['Open','High','Low','Close']]
zip_data = zip(dates.date2num(new_df.index.to_pydatetime()),new_df.Open,new_df.High,\
    new_df.Low,new_df.Close)
# 创建一个画布,并指定大小为宽10英寸、高5英寸
fig = plt.figure(figsize=(10, 5))
# 获取当前活动的子图轴对象
ax = plt.gca()
mpf.candlestick_ohlc(ax,zip_data,width=1,colorup='r',colordown='g')
ax.xaxis_date()
plt.xticks(rotation=45)
plt.title('股票K线图',size = 15)
plt.show()

股票指标相关性分析

核心思想:选出需要的数据列(清洗) 进行一一比对

散点图相关性分析

挑选你认为重要的代表性指标,将各项指标数据两两关联做散点图,发现相关性强的属性对;

此处我选择了调整后收盘价、成交量、最低价,进行一一比对分析:

import seaborn as sns
# 调整后收盘价 成交量 最低价
# 清洗出需要的数据
df_clean = df_numeric_clean_filled[['最低价','成交量','调整后收盘价']]
# 获取列名
columns = df_clean.columns
# 计算列数,用于设置图形网格的大小
num_columns = len(columns)
plt.figure(figsize=(10,8))
# 创建子图网格
plt.subplot(1,3,1)  # 1行3列的子图
plt.scatter(df_clean['成交量'], df_clean['最低价'])
plt.title('成交量 & 最低价')  # 设置子图标题
plt.xlabel('成交量')  # 设置x轴标签
plt.ylabel('最低价')  # 设置y轴标签
plt.subplot(1,3,2)  
plt.scatter(df_clean['成交量'], df_clean['调整后收盘价'])
plt.title('成交量 & 调整后收盘价')  # 设置子图标题
plt.xlabel('成交量')  # 设置x轴标签
plt.ylabel('调整后收盘价')  # 设置y轴标签
plt.subplot(1,3,3)  
plt.scatter(df_clean['最低价'], df_clean['调整后收盘价'])
plt.title('最低价 & 调整后收盘价')  # 设置子图标题
plt.xlabel('最低价')  # 设置x轴标签
plt.ylabel('调整后收盘价')  # 设置y轴标签
# 调整子图间距
plt.tight_layout()
# 显示图形
plt.show()

以下是关于图片反映信息的具体分析:
最低价vs成交量:这个散点图可能用于分析最低价与成交量之间的关系。
如果成交量在最低价时较高,这可能表明在价格下跌时有更多的交易活动。
相反,如果成交量在最低价时较低,可能表明市场对价格下跌的反应不强烈。

最低价vs调整后收盘价:这个散点图可能用于分析最低价与调整后的收盘价之间的关系。
如果调整后的收盘价通常高于最低价,这可能表明股票价格在交易日结束时有所回升。

成交量vs调整后收盘价:这个散点图可能用于分析成交量与调整后的收盘价之间的关系。
如果成交量高时调整后的收盘价也高,这可能表明市场活跃时股票价格也较高。

数据分布统计

挑选你认为重要的指标,绘制直方图,发现指标的分布规律;

此处我选择了绘制 '开盘价' 指标的直方图,进行进一步分析

# 绘制 '开盘价' 指标的直方图
sns.histplot(df_numeric_clean_filled['开盘价'], kde=True)
plt.title('Distribution of Open Prices')
plt.show()

由图分析可得:
频率分布:从直方图可以看出,开盘价的分布并不是均匀的。
在低价位区域(0-1000)的频率较高,特别是在200-500之间,有一个明显的峰值。
这可能意味着大部分开盘价集中在这个区间内。
而在高价位区域(1000-3000),频率逐渐减少,尤其是在2500-3000的区间,几乎没有开盘价出现。

市场趋势:这种分布可能反映了市场对低价开盘的商品或证券有更高的需求或关注度。
这可能是由于低价商品更容易被普通消费者或小额投资者接受。
另一方面,高价位商品或证券的开盘价较少,可能是因为这些商品或证券的目标市场较小,或者它们面临的市场风险更高。

投资策略:对于投资者而言,了解开盘价的分布情况可以帮助他们制定投资策略。
例如,如果投资者倾向于投资开盘价较低的商品或证券,那么他们可能会专注于那些在200-500区间内开盘的选项。
同时,他们也需要注意,高价位区间的商品或证券可能涉及更高的风险。

相关系数(Correlation coefficient)分析

计算各指标数据间的相关系数,得到相关系数矩阵,进一步将相关系数矩阵转换成图形,使用matplotlib.pyplot相关的方法将矩阵可视化;

# 相关系数是用以反映变量之间相关关系密切程度的统计指标。
# 可以使用numpy.corrcof()来直接计算各指标数据间的相关系数。
cov = np.corrcoef(df_clean.T)
print(cov)
# 使用matplotlib.pyplot.matshow() 将矩阵可视化。
# 如下图所示,其中用颜色来代表相关系数,如下图所示,其中用颜色来代表相关系数。
img = plt.matshow(cov)
plt.colorbar(img,ticks=[-1,0,1])
plt.show()

输出结果如下:

[[ 1.         -0.23532835  0.9999057 ]
 [-0.23532835  1.         -0.23354131]
 [ 0.9999057  -0.23354131  1.        ]]

为了更精确的反应相关情况,使用了sns.heatmap()函数

# 计算相关系数矩阵
correlation_matrix = df_numeric_clean_filled.corr()
print(correlation_matrix)

# 绘制相关系数热图
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', fmt='.4f')
plt.title('Correlation Matrix of Stock Indicators')
plt.show()

股票价格趋势线分析

# 读取数据
df_2 = pd.read_csv('Amazon.csv')

# 将日期列转换为datetime类型并设置为索引
df_2['Date'] = pd.to_datetime(df_2['Date'])
df_2.set_index('Date',inplace=True)
# 选择特定日期范围内的数据
new_df = df_2.loc['2000-1':'2000-3',['Open','High','Low','Close']]
# 数据打包 为绘制k线图做准备
zip_data = zip(dates.date2num(new_df.index.to_pydatetime()),new_df.Open,new_df.High,\
    new_df.Low,new_df.Close)
# 创建一个画布,并指定大小为宽10英寸、高5英寸
fig = plt.figure(figsize=(10, 5))
ax = plt.gca()

# 计算5日和20日的滚动平均值 
df_2['5日均价'] = df_2['Close'].rolling(window=5).mean()
df_2['20日均价'] = df_2['Close'].rolling(window=20).mean()
# 仅提取选定日期范围内的移动平均线数据
ma_5 = df_2.loc['2000-01':'2000-03', '5日均价']
ma_20 = df_2.loc['2000-01':'2000-03', '20日均价']
# 绘制k线图
mpf.candlestick_ohlc(ax,zip_data,width=1,colorup='r',colordown='g')
# 绘制移动平均线,只显示选定的日期范围内
ax.plot(ma_5.index.to_pydatetime(), ma_5, label='5-Day Moving Average', color='red', linestyle='--')
ax.plot(ma_20.index.to_pydatetime(), ma_20, label='20-Day Moving Average', color='green', linestyle='--')
# 设置日期格式
ax.xaxis_date()
# 设置x轴标签旋转角度
plt.xticks(rotation=45)
# 设置x轴和y轴标签
plt.xlabel('Date')
plt.ylabel('Price')
# 设置图表标题
plt.title('股票K线图 + 移动平均线',size = 15)
# 显示图例
plt.legend()
# 显示图表
plt.show()

回归分析

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error

# 读取数据
df = pd.read_csv('Amazon.csv')
# 将日期列转换为datetime类型并设置为索引
df['Date'] = pd.to_datetime(df['Date'])
df.set_index('Date', inplace=True)
# 准备数据:选择特征和目标变量
# 这里我们使用'Open', 'High', 'Low'作为特征,'Close'作为目标变量
X = df[['Open', 'High', 'Low']]
y = df['Close']
# 分割数据:将数据分割为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# test_size=0.2: 这个参数指定了测试集应该占原始数据集的比例,这里是20%。也就是说,80%的数据将用于训练模型,剩下的20%将用于测试模型。
# random_state=42: 这个参数设置了一个随机种子,确保每次分割数据时都能得到相同的结果,使得分割过程是可复现的。
# 创建线性回归模型
model = LinearRegression()
# 训练模型
model.fit(X_train, y_train)
# 进行预测
y_pred = model.predict(X_test)
# 计算MAE
mae = mean_absolute_error(y_test, y_pred)
print(f'预测的平均绝对误差(MAE)为:{mae:.4f}')
# 绘制实际值与预测值的关系图
plt.figure(figsize=(10, 5))
sns.scatterplot(x=y_test, y=y_pred, color='blue', label='Actual vs Predicted')
plt.xlabel('Actual Price')
plt.ylabel('Predicted Price')
plt.title('Actual vs Predicted Closing Prices')
plt.legend()
plt.show()
# 为了预测特定日期的数据,我们需要将该日期的数据作为输入
# 要预测1997-6-20的收盘价,我们需要找到该日期附近的数据
input_date = '1997-6-20'
target_date = pd.to_datetime(input_date)
target_date_index = df.index.get_loc(target_date)
# 为了预测,我们需要提供该日期前后的数据(例如,前后各10天)
# 这里我们简单地使用目标日期前后的数据,实际情况可能需要更复杂的方法来选择数据
input_data = X.iloc[target_date_index - 10:target_date_index + 10]
# 使用模型进行预测
predicted_close_price = model.predict(input_data)
print(f'{target_date} 的预测收盘价为: {predicted_close_price[-1]:.4f}')

输出结果如下:

预测的平均绝对误差(MAE)为:1.8057

1997-06-20 00:00:00 的预测收盘价为: 1.8350

  • 32
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值