点击蓝字关注我,有干货领取!

本文对应代码和数据已上传至我的Github仓库:
https://github.com/CNFeffery/DataScienceStudyNotes[1]

已发布:

Python地信专题 | 基于geopandas的空间数据分析—数据结构篇

Python地信专题 | 基于geopandas的空间数据分析-坐标参考系篇

Python地信专题 | 基于geopandas的空间数据分析-文件IO篇

Python地信专题 | 基于geopandas玩转地图可视化

1 简介

通过前面的文章,我们已经对geopandas中的数据结构坐标参考系文件IO以及基础可视化有了较为深入的学习。

其中在基础可视化那篇文章中我们提到了分层设色地图,可以对与多边形关联的数值属性进行分层,并分别映射不同的填充颜色。

但只是开了个头举了个简单的例子,实际数据可视化过程中的分层设色有一套策略方法。

作为基于geopandas的空间数据分析系列文章的第五篇,通过本文你将会学习到基于geopandas和机器学习的分层设色

2 基于geopandas的分层设色

地区分布图Choropleth maps,又叫面量图)作为可能是最常见的一种地理可视化方法。

其核心是对某个与矢量面关联的数值序列进行有意义的分层,并为这些分层选择合适美观的色彩,最后完成对地图的着色。

优点是美观且直观,即使对地理信息一窍不通的人,也能通过颜色区分出不同面之间的同质性与异质性:

图1

但同样地,如果对数据分层采取的方法有失严谨没有很好的遵循数据特点,会很容易让看到图的人产生出不正确的判断。

下面我们按照先分层,后设色的顺序进行介绍。

2.1 基于mapclassify的数据分层

上一篇文章中我们提到过,,在geopandas.GeoDataFrame.plot()中,参数scheme对应的数据分层是基于第三方库mapclassify实现的。

因此要想对geopandas中的数据分层有深入的了解,我们就得先来了解一下mapclassify中的各种数据分层算法。

用到的数据是系列文章前几期使用地滚瓜烂熟的新冠肺炎疫情数据,数据处理过程同上一篇文章,这里不再解释:

图2

2.1.1 BoxPlot

BoxPlot即箱线图,是统计学中使用到的一种方法:

对个数为  观测数据从小到大进行排序,分别得到位置处于 、 以及  的观测值,称为 、 以及 (即第一四位数、中位数和第三四分位数)。

并定义  为 ,以  为下限,以  为上限,将小于下限或大于上限的观测值作为离群异常值。

最后用图像的形式表达上述计算结果,如图2的上图,而图2的下图对应着概率估计。

可以看出,箱线图法实际上是基于概率估计的一种异常值剔除方法,因为离群值只有  的概率会出现,即如果你想要找出数据中的异常高低值,BoxPlot是不错的选择:

图3

mapclassify中我们使用BoxPlot()来为数据实现箱线图分层:

import mapclassify as mc# 对各省2020-03-08对应的累计确诊数量进行分层
bp = mc.BoxPlot(temp['province_confirmedCount'])
# 查看数据分层结果
bp

图4

可以看出通过箱线图法将数据分成了五类,其中异常值只有1个即为湖北省。

下面我们配合geopandas来对上述结果进行可视化,和上一篇文章一样,按照省级单位名称连接我们的疫情数据与矢量数据:

图5

接着对其进行可视化,在上一篇文章图28的基础上,将scheme参数改为BoxPlot,又因为箱线图可以看作无监督问题,故分层数量k在这里无效,删去:

fig, ax = plt.subplots(figsize=(10, 10))ax = data_with_geometry.to_crs(albers_proj).plot(ax=ax,column='province_confirmedCount',cmap='Reds',missing_kwds={"color": "lightgrey","edgecolor": "black","hatch": "","label": "缺失值"},legend=True,scheme='BoxPlot',legend_kwds={'loc': 'lower left','title': '确诊数量分级','shadow': True})ax = nine_lines.geometry.to_crs(albers_proj).plot(ax=ax,edgecolor='grey',linewidth=3,alpha=0.4)ax.axis('off')
plt.suptitle('新型冠状肺炎累计确诊数量地区分布', fontsize=24) # 添加最高级别标题
plt.tight_layout(pad=4.5) # 调整不同标题之间间距
ax.text(-2800000, 1300000, '* 原始数据来源:丁香园,\n其中台湾及香港数据缺失') # 添加数据说明fig.savefig('图6.png', dpi=300)

图6

咋看起来没问题,但是如果你仔细观察左下角的图例会发现前两行范围颜色是重复的,且数值范围是错乱的。

这是geopandas.GeoDataFrame.plot()中涉及箱线图法的一个小bug,遇到这种问题不用慌。

如果你在上一篇文章中去我的Github仓库查看过创作图29对应的代码,一定会想到既然geopandas自身有bug,那我们用matplotlib中的mpatcheslegend自定义图例就可以啦。

而为了自定义的图例色彩与geopandas映射出的保持一致,我们需要额外使用到matplotlib中的get_cmap(cmap)来制作可独立导出颜色的cmap方案实例。

譬如我们这里是Reds,就需要按照前面bp的有记录数量的分层结果,从Reds中产生同样5个档次的颜色,具体操作过程如下:

import matplotlib.patches as mpatchesfig, ax = plt.subplots(figsize=(10, 10))ax = data_with_geometry.to_crs(albers_proj).plot(ax=ax,column='province_confirmedCount',cmap='Reds',missing_kwds={"color": "lightgrey","edgecolor": "black","hatch": "","label": "缺失值"},scheme='BoxPlot')handles, labels = ax.get_legend_handles_labels() #get existing legend item handles and labelsax = nine_lines.geometry.to_crs(albers_proj).plot(ax=ax,edgecolor='grey',linewidth=3,alpha=0.4)# 实例化cmap方案
cmap = plt.get_cmap('Reds')# 得到mapclassify中BoxPlot的数据分层点
bp = mc.BoxPlot(temp['province_confirmedCount'])
bins = bp.bins# 制作图例映射对象列表
LegendElement = [mpatches.Patch(facecolor=cmap(_*0.25), label=f'{int(max(bins[_], 0))} - {int(bins[_+1])}')for _ in range(5)] + \[mpatches.Patch(facecolor='lightgrey', edgecolor='black', hatch='', label='缺失值')]# 将制作好的图例映射对象列表导入legend()中,并配置相关参数
ax.legend(handles = LegendElement, loc='lower left', fontsize=10, title='确诊数量分级', shadow=True, borderpad=0.6)ax.axis('off')
plt.suptitle('新型冠状肺炎累计确诊数量地区分布(截至2020年03月04日)', fontsize=24) # 添加最高级别标题
plt.title('数据分层方法:BoxPlot', fontsize=18)
plt.tight_layout(pad=4.5) # 调整不同标题之间间距
ax.text(-2900000, 1250000, '* 原始数据来源:丁香园,\n其中台湾及香港数据缺失') # 添加数据说明fig.savefig('图7.png', dpi=300)

图7

可以看到,通过自定义图例的方式,虽然麻烦了一点,但是我们不仅修复了图例的bug,还为其添加了更加完善的细节。

如图形修改为矩形,范围修改为整数。

2.1.2 EqualInterval

EqualInterval即等间距,是最简单的一种分层方法。

它在原数据最小值与最大值间以等间距的方式划分出k个层次,mapclassify中对应等间距法的类为EqualInterval()

bp = mc.EqualInterval(temp['province_confirmedCount'])
# 查看数据分层结果
bp

图8

可以看到对于分布非常不均匀的新冠肺炎确诊数量数据来说,这种方法表现得十分糟糕,中间三个类都没有记录落入。

如果使用这种方法强行绘图,效果就会类似上一篇文章中地区分布图部分。

最开始那个糟糕的效果那样只有湖北一个地方是最深的暗红色,而其他地方皆为最淡的色阶,这里就不重复演示。

2.1.3 FisherJenks

在了解mapclassify中的FisherJenks之前,我们先来了解一下什么是Jenks Natural Breaks

  • Jenks Natural Breaks

Jenks Natural Breaks旨在为1维数据计算合适的划分点,使得不同组之间的差距尽可能大的同时组内差距尽可能小。

其思路非常简单,举一个简单的例子进行说明:

对于一组待分割的序列 ,现在需要为其找到将原始数据分为  部分的方法。

那么实际上就有 、 以及  这三种切分方法,现定义sum of squared deviations for array mean(简称SDAM):

以及针对每一种数据分层方法,在其分出的每一组  上计算组内离差平方和并累加所有组的结果,定义为sum of squared deviations for class means(简称SDCM_ALL):

有了  和 ,现在对分组优劣定义一个评判指标goodness of variance fit(简称GVF),取值范围为 ,越高越好:

这样我们就可以对每一种分组方案进行评价,譬如对我们上面简单的例子:

则对应各种方案的GVF计算如下:

可以看出第二种方案  的分层方法效果最好,也与我们对数据的直观感觉相贴合。

这就是Jenks Natural Breaks的基本思路,但这种暴力遍历所有分组方案的做法对数据数量及选择分组的个数很敏感。

尤其是对分组数量,一旦分组数量过于多,待筛选计算的方案数量就变成了天文数字。

下面我来告诉大家为什么:

定义长度为  的序列 。

且满足  时 ,即整个序列从小到大单调递增,那么将其分成  组的过程,可以分解为先选择第一组。

且为了保证右边剩余  个组每组至少有1个数据分配,则第一组有  种分配方式,而第一组包含的数字数量  确定之后,剩余  个数据的继续分组又可以视为独立的递归分组过程。

因此最终需要考虑的方案个数用公式表达起来有些复杂,但是换成计算机中的递归过程就变得一目了然。

我经过思考和纸上的推演,写出了下面所示的递归函数f(n, k)来实现方案总数的计算:

def f(n, k):# 若k退化为2,则显然需要n - 1种方案,譬如4个数字分2组有3种方案if k == 2:return n - 1else:# 若k未退化为2,则继续递归过程return sum([f(n-_, k-1) for _ in range(1, n - k + 2)])

有了这个递归函数,我们就可以来直观的看一看为什么不能选择太多分组。

首先我们对长度为100的序列分为3组试试:

f(100, 3)
Out[11]: 4851

可以看到待选择的方案才4851个,还是很少的,那么我们接下来将组数提高到5:

f(100, 5)
Out[12]: 3764376

发生了什么?随着递归深度的增大,待选择方案数量一下子就提高到三百多万个!再切换成7试一下:

f(100, 7)
Out[13]: 1120529256

在跑上述代码时,明显能感受到计算花费时间的激增,最终结果也达到惊人的11亿多!

看到这,我们就明白了,原始的Jenks Natural Breaks算法虽然很有效,但如果以暴力遍历的方式计算,其复杂度是难以应付日常需求的。

为了对其进行优化,以在少量的计算时间内计算出尽可能靠谱的分组结果,一系列改良加速方法被提出,而mapclassify中的FisherJenks,即为jenks教授在论文Fisher, W. D., 1958, On grouping for maximum homogeneity.的基础上提出的改良算法。

但这是一个很神秘的算法,根据Tom MacWright文章[2] 介绍,jenks教授的原始论文没有留下数字化资料,一直为堪萨斯大学地理学系所私有。

而随着1996年jenks教授的离世,原论文需要到2072年版权才能到期公开,所以我们现在在各种GIS类软件以及各种开源软件包中使用到的fisher jenks算法,均是对最初的一段Fortran代码的移植和改造,这也成了一段未解之谜。

感兴趣的读者可以去文章Natural Breaks Classification[3] 了解更多。

回到我们的主题,搞清楚了FisherJenks的计算目标之后,我们同样利用mapclassify计算分层结果,其默认分层为5:

图9

可以看到,在这种方式下,数据的分组较为合理,同样将geopandas.GeoDataFrame.plot()中的参数设置为FisherJenks绘制出图10:

图10

BoxPlot相比差距还是比较明显,处于第二级严重程度的省份只有河南、广东及浙江,更贴近数据的自然层次结构。

2.1.4 NaturalBreaks

等下!上一小结中的FisherJenks不就是我们俗称的自然断点法吗,怎么又来了个NaturalBreaks

其实我在翻看mapclassify的官方文档看到这里时,也很疑惑。

于是我仔细研究了NaturalBreaks对应的源代码,追根溯源,WHAT?,竟然是k-mean算法,而且直接调用的scikit-learnKMEANS。。。

图11

不过也可以理解,毕竟k-means就是在找数据中组内相似度尽可能高且组间差异尽量大的簇,关于k-means我想我就不需要赘述了,毕竟是最基础的数据挖掘算法之一。

scikit-learn里默认的KMEANS使用的k-means++初始方式,只是在原始k-means基础上,修改了后续初始点的概率密度,使得k-means算法更加鲁棒稳定。

下面直接来看NaturalBreaks的数据分层结果:

图12

FisherJenks的结果竟然一样,但如果你多运行几次会发现这个结果不是完全固定的,由于k-means随机初始迭代起点。

因此不同次运行的结果可能会有轻微差别(图13),在数据量很大时,基于快速聚类法的NaturalBreaks是较为理想的数据分层选择:

图13

配合geopandas绘图只需要把scheme参数修改为NaturalBreaks即可,因为跟FisherJenks类似,这里就不再赘述。

2.1.5 JenksCaspall

mapclassify中的JenksCaspall本质上为k-medians聚类,其首先根据分层层数  在数据中找到  个分位数点,将原始数据等分为数量尽可能相同的  份并以这  份数据的中位数作为各自的初始点。

接着基于k-medians的思想,迭代计算为每个样本点找到与其距离更近的中位数点,并以此重新划分分层以及重新计算各分层中位数点,直至每个数据对应的分层标签不再变化。

再将每个分层中数据的最大值作为间断点,下面我们从mapclassify源代码中抽出该部分代码,对其迭代过程可视化。

具体的代码较多,请在文章开头的Github仓库中对应本文路径下查看:

图14

其中颜色区分对应迭代轮次的数据分层归属,虚线代表对应迭代轮次的间断点,仔细可以看出在迭代过程中数据分层的变化情况。

JenksCaspall数据分层出来的结果,无论数据分布如何,每个分层内部的数据个数都较为均匀,下面我们用JenksCaspall来划分省份疫情严重情况:

图15

可以看到被分到最严重级别的不再只有湖北省,当你希望数据分层个数较为均匀时,JenksCaspall是个不错的选择。

2.1.6 HeadTailBreaks

HeadTailBreaks是一种较为崭新的数据分层方法,出自*Head/Tail Breaks: A New Classification Scheme for Data with a Heavy-Tailed Distribution*[4],专门用于对具有重尾特点的数据进行分层。

所谓重尾即在整个数据中,较小的值数量往往较多,而最大的位于头部的值数量很少,其数据分布呈现出“尾重头轻”的特点:

图16

这种典型如人口密度分布数据,数值较低的点往往数量众多,聚集在尾部,形成重尾,HeadTailBreaks的优点是可以尽量在地区分布图中真实反映原始数据的分布特点。

如图17(https://sites.google.com/site/thepowerofcartography/head-tail-breaks),左边是FisherJenks,右边是HeadTailBreaks,可以看出,右图相对于左图更好地体现了原始数据的重尾特点,最浅色的图斑数量明显多于次浅色的图斑:

图17

geopandas中使用时传入scheme='HeadTailBreaks'即可(由于新冠肺炎各省份确诊数量数据尾部和头部最大值之间没有较为连续的中间值过渡,不太适合用此方法故不作演示)。

2.1.7 Quantiles

Quantiles即分位数,原理很简单,根据分位数点对原数据进行等分:

图18

利用Quantiles对确诊数量分组可视化:

图19

2.1.8 Percentiles

同样是使用分位数对数据进行分层,Percentiles提供了参数pct以允许用户以百分位数的形式传入自定义分隔点。

譬如我们将[1, 50, 99, 100]作为pct的传入值,则分组结果如下:

图20

每个传入的百分位点其左边到上一个分隔点为止,包括其本身,将被分到同一组。

对应的图像如图21,在geopandas中使用时除了设置scheme='Percentiles'之外,还要在另一个字典型参数classification_kwds中传入{'pct': 百分位数列表}

图21

2.1.9 StdMean

StdMean的思想类似前面的箱线图,不同的是箱线图属于非参数方法,而StdMean建立在正态分布为基础的经验法则之上。

即对于正态分布而言,68%的数据将分布在距离均值1个标准差之内,95%的数据在2个标准差之内,99.7%的数据在3个标准差之内

即对原始数据标准化之后,根据距离样本均值的不同标准差范围来划分数据,mapclassify中的StdMean默认按照[-2, -1, 1, 2]来划分:

图22

2.1.10 UserDefined

关于数据分层最后要介绍的是自定义分层,即按照用户输入的分隔点来自由划分数据集,譬如我们按照新浪新闻疫情地图的划分方式:

图23  结合`geopandas`使用时除了设置`scheme='UserDefined'`以外,还要设置`classification_kwds`中的`bins=分隔点列表`:

fig, ax = plt.subplots(figsize=(10, 10))ax = data_with_geometry.to_crs(albers_proj).plot(ax=ax,column='province_confirmedCount',cmap='Reds',missing_kwds={"color": "lightgrey","edgecolor": "black","hatch": "","label": "缺失值"},legend=True,scheme='UserDefined',classification_kwds={'bins': [9, 99, 499, 999, 9999]},legend_kwds={'loc': 'lower left','title': '确诊数量分级','shadow': True})ax = nine_lines.geometry.to_crs(albers_proj).plot(ax=ax,edgecolor='grey',linewidth=3,alpha=0.4)ax.axis('off')
plt.suptitle('新型冠状肺炎累计确诊数量地区分布', fontsize=24) # 添加最高级别标题
plt.tight_layout(pad=4.5) # 调整不同标题之间间距
ax.text(-2800000, 1300000, '* 原始数据来源:丁香园,\n其中台湾及香港数据缺失') # 添加数据说明fig.savefig('图24.png', dpi=300)

图24

2.2 色彩方案的选择

前面已经详细介绍了数据分层常用的各种方法及使用场景,“分层”的部分做完之后,就到了设色的部分。

其实色彩搭配是比较主观的事情,但想要自己创造出美观合理的配色方案并不是容易的事情。

下面我们来介绍两种选择配色方案的方法。

2.2.1 基于palettable的配色

下面我要给大家介绍的Python第三方库palettable在我之前关于词云图的一篇文章中介绍stylecloud时介绍过,是专门帮助我们为可视化作品配色的。

palettable不依赖其他三方库,纯Python实现,其强大之处在于内置了数量惊人的经典配色方案[5]

囊括了CartoColorscmoceanColorbrewer2CubehelixLight & BartleinmatplotlibMyCartaScientificTableau以及The Wes Anderson Palettes blog中的大量经典配色方案:

-palettable.cartocolors.diverging
-palettable.cartocolors.qualitative
-palettable.cartocolors.sequential
-palettable.cmocean.diverging
-palettable.cmocean.sequential
-palettable.colorbrewer.diverging
-palettable.colorbrewer.qualitative
-palettable.colorbrewer.sequential
-palettable.lightbartlein.diverging
-palettable.lightbartlein.sequential
-palettable.matplotlib
-palettable.mycarta
-palettable.scientific.diverging
-palettable.scientific.sequential
-palettable.tableau
-palettable.wesanderson

使用起来非常简单。

譬如如果我们想要使用palettable.cmocean.sequential中的色彩,其中cmocean表示色彩来源,sequential表示连续型色彩,就可以先在对应的示例网页[6]下查看所有方案:

图25

比如我对其中的Dense方案很中意:

图26

就可以按照如下方式,先从palettable中导入对应颜色。

譬如我们导入Dense_20,20表示其自带的离散色彩数量,并查看其自带的离散色彩RGB值、离散色盘以及连续色盘示例:

from palettable.cmocean.sequential import Dense_20
from pprint import pprintprint('对应离散颜色:')
pprint(Dense_20.colors)
print('离散:')
Dense_20.show_discrete_image()
print('连续:')
Dense_20.show_continuous_image()

图27

使用.mpl_colormap将其转换为matplotlib可接受的cmap数据结构,作为cmap参数值传入绘图部分即可:

图28

如果想要翻转映射方向,换成Dense_20_r再重复上述操作即可:

图29

更多palettable自带色彩方案,可以在https://jiffyclub.github.io/palettable/ 下查看探索。

2.2.2 基于图片主色的配色

我们在生活中偶然会看到配色方案让人眼前一亮的海报或画作,这时如果你想将这些作品中的主要颜色也应用到自己的可视化作品上,可以参考我下面的做法。

这里以我很喜欢的贾樟柯导演的《一直游到海水变蓝》中文版海报为例:

图30

思路是抽取所有像素点的RGB三通道值,分别作为三个特征,输入k-means中进行聚类,将聚类数量设置为你想要提取出的主色数量:

from sklearn.cluster import KMeans# 构建特征
rgb = pd.DataFrame([sea[x][y] for x in range(sea.shape[0]) for y in range(sea.shape[1])],columns=['r', 'g', 'b'])# k-means聚类,其中n_clusters表示聚类数量,n_jobs=-1表示开启所有核心并行运算
model = KMeans(n_clusters=5, n_jobs=-1)
model.fit(rgb) # 训练模型# 提取聚类簇重心,即我们需要的主色,绘制调色板
plt.bar([i for i in range(model.cluster_centers_.__len__())],height=[1 for i in range(model.cluster_centers_.__len__())],color=[tuple(c) for c in (model.cluster_centers_ / 255.)],width=1)
plt.axis('off')

图31

再来个例子,提取《一直游到海水变蓝》海外版海报主色:

图32

对应提取到的5种主色如图33:

图33

类似的,你可以试着提取你喜爱的平面作品的主色。

以上就是本文的全部内容,如有笔误望指出。

参考资料

[1]

https://github.com/CNFeffery/DataScienceStudyNotes: https://github.com/CNFeffery/DataScienceStudyNotes

[2]

Tom MacWright文章: https://macwright.org/2013/02/18/literate-jenks.html

[3]

Natural Breaks Classification: https://stat.ethz.ch/pipermail/r-sig-geo/2006-March/000811.html

[4]

Head/Tail Breaks: A New Classification Scheme for Data with a Heavy-Tailed Distribution: https://www.tandfonline.com/doi/abs/10.1080/00330124.2012.700499

[5]

经典配色方案: https://jiffyclub.github.io/palettable/cartocolors/diverging/

[6]

示例网页: https://jiffyclub.github.io/palettable/cmocean/sequential/

-END-

往期精彩回顾适合初学者入门人工智能的路线及资料下载机器学习在线手册深度学习在线手册AI基础下载(pdf更新到25集)本站qq群1003271085,加入微信群请回复“加群”获取一折本站知识星球优惠券,请回复“知识星球”喜欢文章,点个在看

Python地信专题 |基于geopandas的空间数据分析-深入浅出分层设色相关推荐

  1. Python地信专题 | 基于geopandas的空间数据分析-文件IO篇

    本文对应代码和数据已上传至Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 在上一篇文章中我们对geopandas中的坐标 ...

  2. Python地信专题 | 基于geopandas的空间数据分析—数据结构篇

    作者:费弗里 博客地址: https://www.cnblogs.com/feffery/p/11898190.html 说明:本文经作者授权转载,禁止二次转载 全文8500字 本文对应代码已上传至我 ...

  3. Python地信专题 | 基于geopandas的空间数据分析-坐标参考系篇

    文章来源于Python大数据分析,作者费弗里 本文对应代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 在 ...

  4. php中pandans,Python地信专题 | 基于geopandas的空间数据分析-文件IO篇

    本文对应代码和数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 在上一篇文章中我们对geopandas中的 ...

  5. Python地信专题 | 基于geopandas玩转地图可视化

    文章来源于Python大数据分析,作者费弗里 本文对应代码和数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes[1] ...

  6. 基于geopandas的空间数据分析——空间计算篇(下)

    本文示例代码及数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 在基于geopandas的空间数据分析系列 ...

  7. 基于geopandas的空间数据分析—geoplot篇(下)

    文章来源于Python大数据分析,作者费弗里 本文示例代码.数据及文件已上传至Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 ...

  8. 空间计量模型_Stata空间面板数据模型专题直播丨Stata空间计量3月远程直播

    2月28日19:00-21:00Stata空间计量直播专题课(空间面板数据模型)提供全套资料及课后Q&A 空间面板数据模型的前生今世:静态.动态和具有共同因子约束的空间面板数据模型. 模型选择 ...

  9. Python是信奥的基础吗,学习信奥要不要先学python

    2.2 学习信奥不必先学python 2.2 学习信奥不必先学python - 知乎 2.2 学习信奥不必先学python 你真的了解信奥吗?信奥学习误区盘点 你真的了解信奥吗?信奥学习误区盘点 Py ...

最新文章

  1. Delphi对象池MyObjectPool.pas
  2. Beta阶段事后分析
  3. oracle11g exp导出问题:部分表导不出来
  4. ubuntu下的第一个脚本file.sh
  5. VMware Workstation
  6. 操作系统和Linux
  7. 要是有力气的话可以做装卸工,月入过万不是梦
  8. mybatis update返回值的意义
  9. python书写跨越多行的字符串的两种方式
  10. 读书笔记-整理的艺术
  11. [Google] 再见 SharedPreferences 拥抱 Jetpack DataStore
  12. 数据结构与算法——算法知识总览
  13. 降低网站跳出率9种方法
  14. 使用jQuery快速高效制作网页交互特效 第五章 上机练习四 制作广告图片轮播切换效果
  15. 使用Eclipse IDE的技巧
  16. 怎么做手游性能测试?
  17. linux之shell语言
  18. 实现用友U8+与旺店通ERP数据同步
  19. macbook修改账户名称
  20. 织梦插件-织梦插件大全-免费织梦插件大全

热门文章

  1. The Design and Implementation of Open vSwitch
  2. 用户故事与敏捷方法阅读笔记03
  3. 进阶面向对象——类的成员
  4. MySql采用range分区可提升查询效率
  5. springboot入门_shiro
  6. (转) mysqldumpslow使用说明总结
  7. MyBatis在insert插入操作时返回主键ID的配置
  8. Android 通过代码改变控件的布局方式
  9. mysql有三种事务模式_MySQL之事务与三大范式
  10. 计算机进桌面后反复重启,我的电脑一插网线就自动重启。到界面之后又马上重启。一直循环。...