Python学习过程问题记录(三):达内徐铭数据分析快速入门(2022年代码编译遇到的问题)

目录


前言

电脑环境:macOS Monterey 12.2.1、Python3.10.2

工具:Sublime Text 4、Pycharm 2021.3(基本没用)

学习视频:达内教育徐铭2019年9月左右的数据分析课程,后面的人工智能课程没有学习。

虽然是2019年的课程,但大部分代码还是可用,只有少部分在我的环境中调试有问题,特此记录。

Python数据分析全套视频(由浅入深)_哔哩哔哩_bilibili

课件素材:下载地址       密码:USTC  (来源于B站up主-韭财的留言,视频和上面链接的一样,少了后面3个,但没有影响,最后3个也没听太懂)


问题一、matplotlib绘图的中文显示问题

第2天的matplotlib课程。

可能和老师的matplotlib版本不一样,显示的图片的设置少了一些,不过没有影响。

图形左下角的按钮比老师的少一点

后来开始想显示中文的时候出现了口口问题,解决方法参考我之前的记录:Python学习过程问题记录(二):Matplotlib中文显示问题


问题二、图形X轴时间总显示1970年

1.问题描述

第3天的3.13、3.14 numpy加载文件01、02课程。

代码如下,运行后图形X轴应该显示2011年,但却显示了1970年。

import datetime as dt
import matplotlib.dates as md
import matplotlib.pyplot as mp
import numpy as np

# 日期转换函数
def dmy2ymd(dmy):
    dmy = str(dmy, encoding='utf-8')
    time = dt.datetime.strptime(dmy, '%d-%m-%Y').date()
    t = time.strftime('%Y-%m-%d')
    return t

# 读取数据
dates, opening_prices, highest_prices, lowest_prices, closing_prices = np.loadtxt(
    '../da_data/aapl.csv',
    delimiter=',',
    usecols=(1, 3, 4, 5, 6),  # 读取1、3、4、5、6列 (下标从0开始)
    dtype='U10,f8,f8,f8,f8',  # 制定返回每一列数组中元素的类型
    unpack=True,  # 按列拆包
    converters={1: dmy2ymd}
)

# 绘制dates与收盘价的折线图
mp.figure('AAPL K', facecolor='lightgray')
mp.title('AAPL K')
mp.xlabel('Date', fontsize=12)
mp.ylabel('Closing Price', fontsize=12)
mp.grid(linestyle=':')
# 拿到坐标轴
ax = mp.gca()
# 设置主刻度定位器为周定位器(每周一显示主刻度文本)
ax.xaxis.set_major_locator(md.WeekdayLocator(byweekday=md.MO))
ax.xaxis.set_major_formatter(md.DateFormatter('%d %b %Y'))
# 设置次刻度定位器为日定位器
ax.xaxis.set_minor_locator(md.DayLocator())
mp.tick_params(labelsize=8)

dates = dates.astype(md.datetime.datetime) 
print(dates)
mp.plot(dates, closing_prices, color='dodgerblue',
        linestyle='-', label='AAPL')
mp.gcf().autofmt_xdate()
mp.legend(loc=1)
mp.show()

图形X轴日期显示错误

2.问题原因

通过和运行出正确图形的代码对比,发现问题出在:读取文件数据时将dates的类型设为了U10,字符串格式经过datetime.datetime转换不能正常显示日期。

3.解决方法

  • 第一种:在读取文件时就直接设置数据类型为日期类型M8[D]。
# 错误设置
...
dtype='U10,f8,f8,f8,f8',  
...  

# 正确设置
...
dtype='M8[D],f8,f8,f8,f8',  
...  
  • 第二种:读取文件时dates类型可以设置为字符串U10,但在后面通过astype()将类型转换成M8[D]。
...
dates = dates.astype('M8[D]') # 将数据类型U10转换成M8[D]
dates = dates.astype(md.datetime.datetime)
mp.plot(...)
...

两种方法修改后,绘制图形的X轴日期均能正常显示。

图形X轴日期正常显示

问题三、一个括号造成的合成方波差别

1.问题描述

第6天的6.10 三角函数通用函数课程。

代码如下绘制图像时,虽然没有报错,但绘制出的图像和老师的不一样。

import matplotlib.pyplot as mp
import numpy as np

x = np.linspace(-2 * np.pi, 2 * np.pi, 1000)
y1 = 4 * np.pi * np.sin(x)
y2 = 4 / 3 * np.pi * np.sin(3 * x)
y3 = 4 / 5 * np.pi * np.sin(5 * x)

# 叠加正弦函数,合成方波
y = np.zeros(x.size)
print(x.size)
for i in range(1, 1000):
    y += 4 / ((2 * i - 1) * np.pi) * np.sin((2 * i - 1) * x)

mp.grid(linestyle=':')
mp.plot(x, y1, label='y1', alpha=0.2)
mp.plot(x, y2, label='y2', alpha=0.2)
mp.plot(x, y3, label='y3', alpha=0.2)
mp.plot(x, y, label='y')
mp.legend()
mp.show()
我绘制的图像
老师绘制的图像
老师绘制的图像

2.问题原因

通过代码比对,唯一的不同就是我的多了一个括号:

  • 我的: y += 4 / ((2 * i - 1) * np.pi) * np.sin((2 * i - 1) * x)
  • 老师的: y += 4 / (2 * i - 1) * np.pi * np.sin((2 * i - 1) * x)

3.问题分析

一个括号造成一个pi在分母,一个pi在分子,这个完全是粗心问题。


问题四、AttributeError: module 'scipy.misc' has no attribute 'imread'

1.问题描述

第6天的6.11特征值和特征向量课程。

部分代码如下,编译出现错误:AttributeError: module 'scipy.misc' has no attribute 'imread'。

import numpy as np
import matplotlib.pyplot as mp
import scipy.misc as sm
...
# 读取图片,RGB格式
original = sm.imread('../da_data/lily.jpg',True)

# 提取特征值
img = np.mat(original)
eigvals, eigvecs = np.linalg.eig(img)
...

2.问题原因

scipy在新版本中misc库中弃用了一部函数,其中就包括imread,imresize和imsave

  • 可以降低scipy的版本,使用还支持imread的版本,如scipy1.2.1版本。
  • 使用的别的模块代替,我这里使用的是matplotlib.pyplot模块的imread读取图像。

但运行仍存在问题,对读取的图片提取特征量时显示错误:ValueError: shape too large to be a matrix。因为:

  • 使用original = sm.imread('../da_data/lily.jpg',True) 读取的图像是灰度图,original.shape是(512,512)。
  • 使用original = mp.imread('../da_data/lily.jpg') 读取的图像是RGB图,original.shape是(512,512,3)

所以需要将读取的RGB图转换为灰度图,使得图像的shape是(512,512)。

3.解决方法

定义一个RGB图转换为灰度图的函数,代码如下。

  • 0.299、0.587、0.114是设置RGB中加权平均值作为gray。
  • 这三个加权值可以自己设置权重,也可以使用RGB的平均值、最大值等,方法可网络搜索。
def rgb2gray(rgb):        # 将RGB格式转换为灰度模式
    return np.dot(rgb[...,:3], [0.299, 0.587, 0.114])
original1 = rgb2gray(original)

经过这样的转换以后,再提取特征值,就不会报错了。

完整代码如下,绘制图片如图。

  • 但通过函数转换的灰度图直接使用mp.imshow(original1)绘制的图像并不是灰度图,显示颜色比较奇怪,需加上cmap参数才能正常显示灰度图:mp.imshow(original1,cmap='gray')
import numpy as np
import matplotlib.pyplot as mp

mp.rcParams['font.sans-serif'] = 'Microsoft Yahei'  # 显示汉字
mp.rcParams['axes.unicode_minus'] = False
# 读取图片,RGB格式
original = mp.imread('../da_data/lily.jpg')
print(original.shape,type(original),original.dtype,original.size)

# 将RGB格式转换为灰度模式
def rgb2gray(rgb):
    return np.dot(rgb[...,:3], [0.299, 0.587, 0.114])
original1 = rgb2gray(original)    

# 提取特征值
img = np.mat(original1)
print(original1.shape)
eigvals, eigvecs = np.linalg.eig(img)
# 抹掉一部分特征值,生成新图片
eigvals[50:] = 0
dst1 = eigvecs * np.diag(eigvals) * eigvecs.I
eigvals[30:] = 0
dst2 = eigvecs * np.diag(eigvals) * eigvecs.I
eigvals[10:] = 0
dst3 = eigvecs * np.diag(eigvals) * eigvecs.I

mp.subplot(231)
mp.title('读取原图',fontsize=10)
mp.xticks([])
mp.yticks([])
mp.imshow(original)
mp.tight_layout()

mp.subplot(232)
mp.title('转换灰度模式',fontsize=10)
mp.xticks([])
mp.yticks([])
mp.imshow(original1)
mp.tight_layout()

mp.subplot(233)
mp.title("转换灰度模式(cmap='gray')",fontsize=10)
mp.xticks([])
mp.yticks([])
mp.imshow(original1,cmap='gray')
mp.tight_layout()

mp.subplot(234)
mp.title('抹掉部分特征值\n(保留50特征值)',fontsize=10)
mp.xticks([])
mp.yticks([])
mp.imshow(dst1.real,cmap='gray') # 必须加.real不然报错
mp.tight_layout()

mp.subplot(235)
mp.title('抹掉部分特征值\n(保留30特征值)',fontsize=10)
mp.xticks([])
mp.yticks([])
mp.imshow(dst2.real,cmap='gray') # 必须加.real不然报错
mp.tight_layout()

mp.subplot(236)
mp.title('抹掉部分特征值\n(保留10特征值)',fontsize=10)
mp.xticks([])
mp.yticks([])
mp.imshow(dst3.real,cmap='gray') # 必须加.real不然报错
mp.tight_layout()
mp.show()
绘制的图片

问题五、matplotlib.pyplot 有个子图不显示(tight_layout()问题)

1.问题描述

第7天的7.11杂项之图像课程。

代码如下,但绘制出的图像有个子图不显示。

import numpy as np
import matplotlib.pyplot as mp
import scipy.ndimage as sn

mp.rcParams['font.sans-serif'] = 'Microsoft Yahei'  # 显示汉字
mp.rcParams['axes.unicode_minus'] = False

#读取文件
original = mp.imread('../da_data/lily.jpg', True)

# 将RGB格式转换为灰度模式
def rgb2gray(rgb):
    return np.dot(rgb[...,:3], [0.299, 0.587, 0.114])
img = rgb2gray(original)    
#高斯模糊
median = sn.median_filter(img, 21)
#角度逆时针旋转45度
rotate = sn.rotate(img, 45)
#边缘识别
prewitt = sn.prewitt(img)

mp.figure('图像',facecolor='lightgray')
mp.subplot(221)
mp.imshow(img, cmap='gray')
mp.title('原图变灰度图',fontsize=10)
mp.xticks([])
mp.yticks([])
mp.tight_layout()

mp.subplot(222)
mp.imshow(median, cmap='gray')
mp.title('高斯模糊',fontsize=10)
mp.xticks([])
mp.yticks([])
mp.tight_layout()

mp.subplot(223)
mp.imshow(rotate, cmap='gray')
mp.title('角度旋转',fontsize=10)
mp.xticks([])
mp.yticks([])
mp.tight_layout()

mp.subplot(224)
mp.imshow(prewitt, cmap='gray')
mp.title('边缘识别',fontsize=10)
mp.xticks([])
mp.yticks([])
mp.tight_layout()

mp.show()
其中一个子图不显示

2.问题原因

只知道是使用了mp.tight_layout()的原因,可以参考一下帖子。matplotlib之pyplot模块——调整子图布局(subplots_adjust、tight_layout)

tight_layout函数概述
tight_layout函数的功能为子图的内边距。备注:对axes()函数生成的子图无效。

函数的签名为matplotlib.pyplot.tight_layout(*, pad=1.08, h_pad=None, w_pad=None, rect=None)

函数的参数如下:

pad:所有子图整体边缘相对于图像边缘的内边距,距离单位为字体大小的比例(小数,与rcParams["font.size"]相关)。可选参数。浮点数。默认值为1.08。
h_pad, w_pad:子图之间的内边距,距离单位为字体大小的比例(小数)。可选参数。浮点数。默认值为pad。
rect:绘制子图的矩形区域的归一化坐标。可选参数。4元组(left, bottom, right, top)。默认值为(0, 0, 1, 1)。

3.解决方法

将不显示的那个子图mp.subplot(223)的紧凑布局代码mp.tight_layout()注释掉,修改后如下:

...
mp.subplot(223)
mp.imshow(rotate, cmap='gray')
mp.title('角度旋转',fontsize=10)
mp.xticks([])
mp.yticks([])
# mp.tight_layout()    # 注释掉此句代码,该子图即可正常显示

另外试了一下,设置mp.tight_layout的w_pad参数大于4也可以显示,但显示效果不如不使用tight_layout好。

绘制的图像正常显示:

子图正常显示

总结

以上就是数据分析这8天的学习过程遇到的问题。

第99~101个视频的2.2、2.3、2.4项目实战:项目环境配置等课程,因为没有Ubuntu环境没有进行学习。

猜你喜欢

转载自blog.csdn.net/yearx3/article/details/123310324