EXCEL中如果A1假设数据段定义如下DA1等于0,那么B1显示“完成计划”,如果A1大于0,那么显示“超额完成“空值显示计划中?

Ocean Data View,简称ODV。虽然名称上强调的是海洋数据,但其实还可以进行大气、陆地、冰盖、海冰、沉积物数据的可视化展示与制图。从读博开始才知道有这么个软件,感觉像发现了新大陆,觉得很有意思。它不仅可以画空间站位图、平面分布图、垂向剖面图、散点图,还能绘制时间序列图、轨迹图等。在数据交互查看、分层显示上也有一定的优势。当时虽然身边很多同学都知道怎么用它来画图,但成图的质量不是很高。在慢慢接触、摸索的过程中,我也发现了一些问题,比如数据不能正确导入、高分辨率地形如何加载、如何添加或操作文本、如何分批显示数据、如何准确勾勒研究区域、如何进行配色和美化等。虽然ODV有比较详尽的用户指南https://odv.awi.de/fileadmin/user_upload/odv/misc/odvGuide.pdf,网上也能找到一些讲解ODV制图的PPT材料,但是时常找不到解决方案。只能通过跟周围同学、老师的讨论,自我摸索,才逐渐积累到一些小技巧,可以有效画出准确、美观的成图。当然我也知道ODV的局限性所在,平时也会用Matlab或Python来制图,更加自主、灵活。但我至今还没有放弃它,是因为我还没有解决DIVA插值法在Matlab或Python上的应用。这个插值法的优势在于可以基于地形进行插值,即插值方法受到地形的约束。另外,对于敲代码就头疼的同学来说,ODV将是个不错的制图选择。ODV有自己的官网ODV: ODV,可查看详细的简介、功能以及操作以及软件的下载与安装。对于非商业、非军事以及教学用途,ODV基本是免费的。如果用于科研论文、报告或者海报展示,ODV必须进行如下引用:Schlitzer, Reiner, Ocean Data View, odv.awi.de, 2021。对于商业和军事用途,必须购买ODV软件许可,更多信息参见 ODV license document。ODV may be used free of charge for non-commercial, non-military research and teaching purposes. If used in scientific papers, reports or posters, ODV must be referenced as follows: Schlitzer, Reiner, Ocean Data View, odv.awi.de, 2020. Usage of ODV for commercial and military purposes requires purchase of an ODV software license. For more information please see the ODV license document.感谢在写作过程中各位朋友的提问与讨论,我在这过程中也学习或探索了不少新的技巧。希望感兴趣的朋友提出宝贵的意见和建议或者问题,使我们能最大化利用好ODV这个软件,同时我们能绘制出精美的图件。* 常见问题与解决方案见文末附录* 如有问题,在文中或留言中没有找到解决办法,亦可发邮件至zyylibra@126.com,请在邮件标题中包含“知乎ODV”字段* 转载请联系我(zyylibra@126.com)并注明出处,仅用于学术交流,谢谢合作!* ODV部分操作指导视频更新在绘图软件概述与Ocean Data View入门操作-赵秧秧,适合刚接触ODV的人快速入门一、ODV的下载与安装免费注册后,即可在Software -> Download菜单栏下面,选择自己电脑系统对应的版本进行下载(Windows, MacOS, Linux)。建议下载最新版本,最新版本不仅修复了一些bug,而且版本之间只能向下兼容,即对于新版本生成的文件在旧版本ODV中可能打不开。注意:ODV 5.0版本只适用于64位电脑系统,如果电脑是32位系统,请安装4.7.10版本。电脑系统是windows 10及之后的版本,请安装对应windows版本的odv_[版本号]_x64.exe文件;如果是windows 10之前版本的电脑系统,请安装对应windows版本的vc_redist.x64.exe文件。ODV 4.7.10 版本:Windows版本ODV_4.7.10: 链接: https://pan.baidu.com/s/1z1NPDDAhNlJg5ZvbxoimZQ 提取码: 6885ODV 5.4.0版本(2021-04-27):Windows版本ODV_5.4.0: 链接:https://pan.baidu.com/s/1mI64ClEnuJ2v9x50_rDiuw
密码:kie2MacOS版本ODV_5.4.0: 链接:https://pan.baidu.com/s/1PCh6lkkBBd-UyGhQubd8dA
密码:d5qtODV最新5.6.2版本(2022-04):Windows版本ODV_5.6.2:链接: https://pan.baidu.com/s/10HwmKgE6twJFBGEslzfC4Q 提取码: wy5uMacOS版本ODV_5.6.2: 链接: https://pan.baidu.com/s/1y03-o1fqO3XOixEj8W7Cvw 提取码: p3q4https://pan.baidu.com/s/1a6EEoJ0fYDqBxFS2BTGg-g
密码: 39tl最新版安装包内附更新说明和安装说明,有需要可查阅。二、数据导入ODV支持很多常规数据格式,比如.odv, .var, .nc, .cdf, .grd, .txt, .csv, .o4x等。最常用的可能是标准netCDF格式(.nc)和自己生成的数据文件(.txt 或 .csv)。nc文件的导入相对比较简单,这里主要要简单介绍Excel文件.csv的导入。1)打开ODV,菜单栏File -> Open,在弹出的窗口Files of Type下拉菜单中选择你需要打开的文件类型,然后找到你需要打开的文件,选中,点Open打开。* 文件名建议以字母、下划线"_"和数字的组合形式命名,避免使用特殊符号(以中文命名的文件也可正常导入)。* 文件内容尽量不要出现中文(待确认)。2)弹出Spreadsheet File Properties窗口,在Lines窗口会显示文件中识别的内容,在页面中选择对应的数据分隔符Column Separator,并设置参数名称行号、单位行号和第一行数据的行号。Text Quotation String和Missing Value Indicators默认设置即可。设置完后,会在Column Labels栏显示分隔好的参数名称。确认无误后点击OK即可。3)弹出Metadata and Data Variables窗口,共分为三个模块,左边是Import Variables, 会显示可以导入的参数及对应的单位,右上是Metadata Variables,一般默认会有一些参数(可能在导入参数中没有,没关系),右下是Data Variables,一般把Metadata Variables中已经包含的参数从这个Data Variables中移出,即选中参数,点击向左箭头;同理,想把导入的参数添加到Metadata Variables中,在Import Variables中选中参数,点击向右箭头即可。在点击OK之前,primary variable选择最主要的默认显示变量,站位剖面可以选择水深,时间序列可以选择时间。* 如果需要画垂向剖面图,且会使用到实测的地形,在导入文件站位深度一栏,参数名称最好设置为“Bot. Depth [m]”,一定要带单位!!!(可以单独一行或者参数名和单位分成两行显示)在导入时确认Metadata Variables中自动显示Bot. Depth这个参数,不然可能匹配不上,后期画图时不能实现实际地形的绘制。4)弹出Collection Properties窗口,选择数据所对应的数据领域(海洋、大气、陆地、冰盖、海冰、沉积物)、数据类型(剖面、轨迹、时间序列)以及主要显示参数(同上一个窗口)。5)弹出Meta Variable Association窗口,即导入数据与默认Metadata Variables的关联,通常站位、经度、纬度、底层深度等自动匹配没问题,主要是时间的匹配。在默认的Metadata Variables会把时间拆解成年、月、日、时、分、秒,所以如果导入的时间没有拆解开,可以通过Convert进行转化,但需要注意这里时间可以转化的类型(图2.1)。通常把日期和时间分成两行导入,匹配日期是,只需要在左边Source Variable中选择日期参数,右边选择Year,然后点击中间的Convert即可,匹配后会在右侧的Year, Month, Day前面显示星号(*);时间匹配操作方法同理。匹配完后点击OK即可。图2.1 ODV中日期和时间转化格式列表6)弹出Import Options窗口,对于第一次新建文件,Import Mode默认即可;对于原有文件也可以进行添加或者替换站位数据。在下面的Data Variable Association模块中可以确认是否导入的参数关联正确,尤其是当导入的参数中有相同的参数名称的时候。确认完,点击OK。7)弹出Import窗口,正确导入的话会显示生成的数据集Collection的存储位置,导入的站位数(图2.2);如果不能完全正确导入,在窗口中会显示Warning,需要确认哪一个环节导致数据不能完全正确导入。图2.2 ODV数据导入正确的弹窗信息自此,数据导入结束,导入的站位会根据经纬度在地图中显示。*特别说明:时间序列数据的导入,除了常规的日期和时间外,需要另外加一列数字格式的时间,可以是真实时间(日期+时间 -> 转成数字格式),也可以根据画图需要另设成一定的单位,比如从时间序列观测开始时设置为第0小时或第0天。三、站位图绘制与美化3.1 站位图的基本绘制方法数据导入到ODV之后,会在地图上显示导入的站位。如果显示的是全球分布图,而研究区域很小,则可以通过右键单击选择Full domain来将研究区放大显示。在地图上右键单击,选择属性Properties,在弹出的属性设置窗口Main Properties中进行设置:1)在General模块, 在Palette中选择地图的配色方案(添加外源配色方案见3.4 - cmocean配色方案的加载),在Font Base Size设置字体大小,在Axis Color设置地图轴颜色,在Draw Grids添加或取消网格线,在Draw Labels显示或取消标签2)在Display Style模块,选择站位的大小和颜色(只能把所有站位设置成统一的大小和颜色,自定义的设置见“3.2-站位标记的多重批次批量显示”)3)在Domain模块,设置站位图的经纬度范围(纬度北为正,经度东为正)4)在Projection模块,选择投影方式,主要有正交投影、墨卡托Mercator投影和Mollweide投影;设置地图中心的经纬度,在大尺度空间显示时可能需要调整站位在空间分布的协调性会用到5)在Layers模块,选择地形(高分辨率地形加载见“3.3-高分辨率地形的加载”),设置陆地地形、海洋地形的等值线及配色,以及是否显示河流、海岸线、国界线等(具体设置见“3.4 - 地形显示的自定义设置”)6)在Annotations模块,选择是否在站位边上显示站位名(选择后,需要在地图上双击目标站位,才会在站位边上显示站位名,但该站位名不能通过拖动进行移动,而是需要选中站位右键单击选择Manage Pick List -> Edit Pick List,选中需要更改位置的站位名,点击右侧的Edit进行修改,在Annotation Alignment中对X和Y分别进行选择,其中的left/right/top/down是站位相对于站位名而言的。选中后直接按删除键Delete即可删除站位名)选择及设置完毕后,点击OK即可。当然我们可以自定义设置,进一步美化站位图。3.2 站位标记的多重批次批量显示两种办法进行多重批次批量显示:逐批手动选择站位:在地图上右键单击的菜单栏,选择Extras -> Add Graphics Object -> Symbol Set,在弹出的Symbol Set - Selection窗口中,选择需要同一标记显示的航次和站位(按住Control可以选择多个站位),选择完毕后点击“<<”按钮,即完成该批次的选择;接下来可以选择第二批次的站位,步骤同上,依次类推。所有批次选择结束后,点击OK,会弹出标记设置窗口,这里的设置是针对刚才所有批次的。通过站位筛选进行批量选择:在导入数据前如果有针对数据批次的参数,可作为站位筛选的目标参数,可以是采样时间、空间范围、航次号等;如果以上参数都重叠,则需要在导入数据前另设一个参数来表示不同的批次,最好是数字,方便选择,比如航段Leg,不同航段分别设置1,2,3...。在导入数据过程中,将该参数归类到Metadata variable部分。站位筛选:地图上右键单击选择station filter,在弹出窗口Metadata菜单下方的左边选择之前设置的区分批次的参数,然后在下方Acceptable range中填相应批次的数据,如果仅一个批次,则范围两端数值一致即可。然后重复上述1中的操作,在地图上右键单击的菜单栏,选择Extras -> Add Graphics Object -> Symbol Set,在弹出的Symbol Set - Selection窗口中,选择所有显示的站位,选择完毕后点击“<<”按钮,即完成该批次的选择进行设置。然后重复station filter的步骤选择和设置第二批次站位标记。如果只有一个批次,可以直接设置该批次站位的图例、标记类型、大小、填充和边框颜色、边框线粗细、站位间连线类型/粗细/颜色,最后勾选或取消是否可以移动、是否添加到图例中等。如果有多个批次,默认设置,点击OK关闭标记设置窗口。将鼠标光标移动到地图任意一处,右键单击,在弹出的菜单栏中选择Extras -> Manage Graphics Object;或者将鼠标光标移动到新添加的标记上,右键单击,在弹出的菜单栏中直接选择Manage Graphics Object。依次选择不同批次的站位进行标记属性设置。这里还能选择到图例对象,选中后点击edit即可进行图例显示的编辑,包括图例位置、字体颜色和大小、背景色、边框颜色和粗细以及图例是否可以拖动。设置完成后,不同批次的站位可以同时显示在同一地图上了。3.3 高分辨率地形的加载在网络状态良好的情况下,Windows系统用户在View -> Settings中,MacOS系统用户在odv -> Preferences中,点击Gridded Bathymetry或者Map下的Resources,窗口右侧即出现可供选择的高分辨率地图(如果未显示,可能是网络状态不给力),没有特殊要求,可以选择全球常用高分辨率地图ETOPT1_2min或GEBCO_2014_2min。如果是空间大尺度显示,可以ETOPO1_6min或GEBCO_2014_6min产品;或者小尺度显示,选择GEBCO_2014_30sec产品。这里还提供针对特定区域的高分辨率地图,选中任意一个产品,右边Install按键会变亮,表示可以安装,点击按键即开始自主加载选中的地图产品。在模块下方同时显示针对该产品的说明。一般加载进度会在ODV窗口下方显示,没有加载信息可能是因为网络不给力,可以换个网络连接试试。当然,还有手动加载的方式啦!找已经加载完地图的人,在其ODV的用户文件夹下(用户文件夹路径可通过Windows: View -> Settings或MacOS: odv -> Preferences打开设置窗口,在System下面的User Directory中可以找到;图3.1)的bathymetry文件夹中,将对应地图产品的.nc文件和.settings文件拷贝到本人ODV用户文件夹的bathymetry文件夹中即可。另外,将ODV安装包的coast文件夹中的对应地图产品文件夹整个拷贝到本人的对应路径下即可。图3.1 ODV用户文件夹路径加载完毕后,在ODV地图上右键点击属性Properties,在弹出窗口的Layers模块,取消勾选Automatic Selection,在Series中可以选择加载的其它地形产品。Bathymetry产品:链接:https://pan.baidu.com/s/1tdl7n3f_-KDKoneCkFFeaw
密码:epefcoast文件夹ETOPO1: 链接:https://pan.baidu.com/s/1C04IwDLhmwLDxvdr6q50Gw
密码:6r7x3.4 高分辨率地形显示的自定义设置地形显示有两种方式,一种是基于加载的高分辨率地形产品进行编辑,另一种是导入外源地形文件进行显示。第一种情形:1)在地图上鼠标右键单击,选择Properties选项,在弹出的Properties窗口General模块中,设置palette,选择合适的配色方案,点击OK确认后,对于这个地图的配色方案会相应地更改2)重新打开Properties窗口,在Layers模块中取消Automatic Selection勾选,选择自主加载的高分辨率地形产品,同时Layer Selection的内容也会随之更改。其中,带pre-或post-的选项主要包括海洋边界、国界、湖泊和大、中、小型河流的设置,Ocean Bathymetry, Coastline和Land Topography分别对应海洋等深线、海岸线和陆地地形的设置。3)以选择Ocean Bathymetry为例介绍如何设置等深线- 选择Ocean Bathymetry,点击右侧的Compose按键打开Ocean Bathymetry Layer Set窗口(图3.2),左侧Selected下面是已经默认选择好的图层,中间Available下面是该地形产品所提供的所有图层,根据需要添加或删除图层- 添加图层:在Selected或Available板块中选择某一深度,在Line下面设置线条粗细、类型以及颜色,并选择是否填充相邻等深线之间的区域,这里供选择的颜色跟步骤 1)中选择的配色方案有关。设置完毕后,点击“<<”按键(必不可少!!!不然相当于没设置),即可将该深度图层添加到Selected中- 删除图层:在Selected板块中选择某一或多个深度图层,点击“>>”按键,即完成图层的删除* 总体来说,目前暂未发现有更为便捷的设置方法,只能逐一设置;颜色的选择可以根据颜色渐变进行依次选择图3.2 海洋等深线设置窗口4)陆地等高线与地形、海岸线、湖泊、河流、边界设置操作步骤同3)第二种情形:1)将外源地形文件转化成.gob格式,放到该ODV设置文件夹(文件名.Data)里面的gobjects文件夹中2)在地图上右键单击,选择Extras ->
Add Graphics Object from File -> GOB file,自动打开该ODV设置文件夹的gobjects文件夹(如果未将外源地形文件放置在这里,请找到外源地形文件的地址),选择外源地形文件,点击OK即可* 如果仅设置等深线而不进行颜色填充,那么需要手动添加等深线标记(参见“3.6 要素的自定义添加与设置”)3.5 cmocean和scientific color maps配色方案的加载在原有ODV自带配色方案的基础上,cmocean也提供了可用于ODV的配色方案。关于cmocean的介绍详见:Beautiful colormaps for oceanography:cmocean的配色方案如图3.3所示(下载自https://matplotlib.org/cmocean/#cmocean-available-elsewhere)图3.3 cmocean配色方案Scientific Colour Maps同时作为提倡感知上统一、有序、对视觉缺陷者友善而设计的colormap (http://www.fabiocrameri.ch/colourmaps.php),虽然提供了适用于很多软件的colormap(图3.4),但是暂时没有适用于ODV版本的。作者根据Scientific Colour Maps提供的*.pal文件,基于ODV palettes的配色规则编译了适用于ODV版本的colormaps (*_odv.pal),同时添加了逆向colormaps (*_r_odv.pal)文件。图3.4 Scientific colour maps配色方案加载到ODV步骤:1)从cmocean官网下载适用于ODV的文件包:kthyng/cmocean-odv;或者从下方链接中下载cmocean或Scientific Colour Maps适用于ODV的配色文件;2)将下载到的*.pal文件放到ODV用户文件夹的palettes文件夹中即可(用户文件夹路径可通过windows: view -> settings或macOS: odv -> preferences打开设置窗口,在system下面的user directory中可以找到;图3.1);3) 如前所述,使用这些配色方案,在ODV图件上右键单击,选择Properties选项,在弹出的Properties窗口的General模块中,在Palette中选择。cmocean的ODV版本:链接:https://pan.baidu.com/s/1gXy50JHiU7B0sicQC36BjA
密码:0hwiScientific Colour Maps的ODV版本:链接:https://pan.baidu.com/s/11F5N39LaVxYm4GHzPkysVA
密码:604n3.6 要素的自定义添加与设置可供自定义添加的要素主要包括文本、线条、椭圆、多边形、折线、矩形、符号以及符号组,其中符号组的添加在“3.2 站位标记的多重批次批量显示”中已有介绍,不再赘述。要素的自定义添加均可通过在ODV图件上右键单击,选择Extras -> Add Graphics Object,选择需要添加的要素。1)文本:选择Annotation, 在图件上任意选择一个位置单击,弹出该文本标记的设置窗口(图3.5),设置该文本标记要显示的内容、位置、对齐方式、文本颜色、大小、旋转角度、背景颜色、边框颜色和粗细,最后可以选择该文本标记的归属(当整个画布内有多个图时需要注意该选项)以及是否可以拖动,设置完毕后点击OK即可。图3.5
文本标记属性设置窗口2)线条:选择Line, 在图件上依次点击线条的起止点,弹出该线条的设置窗口(图3.6),在Line板块设置该线条的粗细、类型、颜色,在X/Y Nodes板块可以更改线条的起止位置(如在地图上添加,则X/Y分别为经/纬度),在Start type和End type板块分别设置线条的端点类型和大小,最后可以选择该线条的归属(当整个画布内有多个图时需要注意该选项)以及是否可以拖动,设置完毕后点击OK即可。图3.6 线条属性设置窗口3)多边形:选择Polygon, 在图件上依次点击多边形的节点,最后双击结束选择,弹出该多边形的设置窗口,该窗口与2)中线条的设置窗口类似,除X/Y节点更多之外,其它都一致。4)符号:选择Symbol,在图件上点击符号添加的位置,弹出该符号的设置窗口(图3.7),可以设置符号的位置、类型、大小、填充色(可供选择的颜色与所选择的配色方案有关)、边框颜色和粗细,最后可以选择该线条的归属(当整个画布内有多个图时需要注意该选项)以及是否可以拖动,设置完毕后点击OK即可。图3.7 符号属性设置窗口其余要素的设置与上述步骤 1) - 4) 相似,不再赘述。3.7 图件和要素的保存图件常用保存分为两种方式,一种是直接生成图片(保存后不能修改),另一种是保存为*.view文件,后期修改可以直接加载后修改。1)单一图件直接保存:在需要保存的图片上右键单击,save map as(地图)或save plot as (除地图外的其它图件),弹出保存窗口,设置保存路径和图片格式(*.jpg, *.png, *.tif, *.gif, *.eps),设置完成后点击save即可。2)画布所有图件保存成一个图:在画布空白处右键单击,save canvas as,弹出保存窗口,设置保存路径和图片格式(*.jpg, *.png, *.tif, *.gif, *.eps),设置完成后点击save即可。3)保存为.view文件:在ODV窗口最上边的菜单栏中点击view,在下拉菜单中选择save view as,弹出保存窗口(默认路径为该数据对应的ODV设置文件的views文件夹),设置文件名称,设置完成后点击save即可。下次需要在此基础上修改,直接通过view -> load view找到需要修改的*.view文件,即可加载进来继续修改。自定义添加要素的保存主要是方便以后在不同ODV数据文件中再次用到,保存方式分为两种:1)对于站位点、等值线、断面地形和断面站位标记,在图件上右键单击,选择Extras -> Export as Graphics Object,选择对应的输出要素保存为*.gob文件(默认路径为该数据对应的ODV设置文件的gobjects文件夹)2)对于所有自定义添加要素,在图件上右键单击,选择Extras -> Manage Graphics Objects...,弹出该图件上所有的自定义添加的要素窗口(图3.8),选择需要导出的要素(可通过shift或control进行连续或不连续多选),选择完成后点击Export进行保存。* 通过该窗口设置,可以对自定义要素进行编辑、复制、删除和排序。图3.8 自定义添加要素设置窗口四、平面分布图的绘制与技巧4.1 平面图的基本绘制方法简单地说,绘制平面分布图,就是把同一层的参数绘制在一起。当然这里“同一层”可以是表、底层,可以是固定深度层或者以某个参数为标准来定义,比如同一密度层等。那么在绘图之前需要先计算得到这个同一层的数据:在ODV最上边的菜单栏中选择View -> Isosurface Variables...,弹出窗口中(图4.1),在New模块下从左往右依次设置需要绘制的参数、层位设置所依据的参数以及该参数的数值或属性。最常见的以深度为层位设置标准,最右端可以选择最上层first,最下层last,或者该参数的最大值和最小值;当然也可以设定固定值作为该层位的选择标准,比如固定深度10 m等(具体设置需要注意的问题详见4.2同层参数设置注意事项与解决办法)。图4.1 等值层参数计算接下来画图步骤简述如下:1)在ODV最上边菜单栏,选择View -> Layout Templates,这里提供了多种绘图模板(图4.2),包括全屏地图、单个或多个站位图、散点图、断面图、平面分布图等。这里选择以单个平面分布图1 SURFACE Window为例绘图。图4.2 绘图窗口模板2)选择1 SURFACE Window后,ODV画布中会出现一个平面散点分布图,在分布图上右键单击Properties,在弹出窗口中对图件进行设置。3)Properties窗口中General模块的设置与站位图类似,见”3.1 站位图的基本绘制方法“的步骤(1);4)Properties窗口的Data模块中,在Scope中仍可以选择需要绘制图件的类型(站点剖面分布图、散点图、断面图和平面分布图),分设X轴、Y轴和Z轴,一般平面分布图的X轴和Y轴设置为经纬度,Z轴为需要绘制的同层参数。选择参数后,点击X-Axis Setting或Y-Axis Setting可以设置图件所需要展示的经纬度范围、刻度间距和刻度数值间距以及刻度展示的位置(图4.3),点击colorbar setting可以设置参数范围以及colorbar的刻度间距和刻度数值间距以及colorbar的位置。当然,这些轴的数据展示都提供逆序选项(需要逆序的话,勾选reverse range即可)。左下角可以勾选apply to all windows将该模块的设置应用到所有ODV画布中所展示的绘图窗口中。图4.3 坐标轴属性设置5)Properties窗口的Display Style模块中(图4.4),平面分布图可以选择以散点站位的形式展示,也可以对空间分辨率较高的数据进行插值填充展示。散点站位的形式,可以选择带颜色的点、有大小的点、数值或箭头的形式,下方还能设置符号的大小、颜色以及线条的粗细。填充的形式,首先需要选择插值方式,包括快速插值、权重平均插值和DIVA插值,总体来说插值的效果DIVA最好(其优势在于考虑地形因素,三角网格插值,具体说明见ODV用户指南https://odv.awi.de/fileadmin/user_upload/odv/misc/odvGuide.pdf的16.6.2 DIVA gridding),但是对于站位空间分布比较散的情况,不建议用插值填充的方式。一般默认勾选自动插值尺度,如果需要设置插值在x轴和y轴的分辨率,可以勾掉这个选项,在下方填入数字。还可以设置隐藏低于某一标准的数据,是否进行填充(不填充的话就是绘制等值线图),是否不包括孤立点或离群点。即使进行填充的情况下,仍可以选择绘制站位点,对其大小和颜色进行设置。图4.4 数据展示类型设置6)Properties窗口的Contours模块中,可对等值线进行设置(不需要设置的可以直接略过这一步),如图4.5所示。等值线的添加方法:设置等值线的最小值(Start)、间距(Increment)和最大值(End),生成等差数列,在设置完线条的粗细、颜色、类型,标签的大小和显示频率,以及等值线之间填充的颜色后,点击<<按键,设置完的等值线数据会添加到左侧Already Defined板块中。如果设置单独一条等值线,最大值和最小值输入同一数值且间距为非零数据即可。* 实际生成的等值线的最大值等于或小于End中输入的数值。* 点击auto-create按键可以根据数据自动生成非单一等差等值线,比如5、10、15、 20、25、30、33.6、33.8、34.0。图4.5 等值线设置7)Properties窗口的Color mapping模块中,可以设置colorbar的中值所对应的颜色以及该配色系列的非线性程度(nonlinearity),该界面还提供自动调整和恢复到线性分布两个功能(图4.6)。图4.6 Colorbar设置8)Properties窗口的DIVA Settings模块中,如果选择了DIVA插值方式,这里可以设置插值的信噪比以及是否防止出现负值,选用的地形数据文件等(图4.7)。图4.7 DIVA插值设置4.2 同层参数设置注意事项与解决办法在设置同层参数中,往往因为设置方法不正确、某些站位某些层位的数据缺失,导致最终绘制的平面分布图存在偏差,误导我们对结果的描述和解释。因此需要特别注意一下几点:1)如果需要绘制的参数跟设置的参数的数值对应不上,则该层中不显示数据。比如需要绘制深度为5 m的盐度平面分布图,但是某些站位没有深度为5 m的盐度数据,那么在该盐度5 m层数据中没有这些站位的盐度数据,ODV不会自动根据小于和大于5 m层位的数据来插值计算5 m层位的数值。2)对于绘制表、底层的平面分布图,如果某些站位的表层数据或底层数据缺失,那么ODV会自动在该站位用相邻层位的数据来补充,这样就可能导致最终的平面分布失真。比如在某一站位缺失了表层的盐度数据,但是还有中层和底层的数据,那么在选择first以层位选择基准的时候,会将中层的盐度数据放到该表层同层数据库中。我的解决办法是通常在数据导入前给层位设置layer_flag,以数字表示,比如三层的话,表、中、底层分别设为1、2、3。在绘图时有两种方式可以避免上述平面分布失真的情况:- 在同层数据设置中,不选择深度,直接选择layer_flag,设置layer_flag = 数值1,2或3;- 如果不在同层数据设置中以layer_flag为选择标准,那么在Properties窗口设置完毕关闭后,在平面分布图上右键单击选择Sample filter -> Customize settings,在弹出的窗口中选择Range模块(图4.8),Variabe选择Layer_flag,将Acceptable Range设置成对应的层位,那么即使有其它层位的数据掺杂到该层位的平面分布图中,通过这个办法也能将它剔除。图4.8 等值层参数设置3)对于多个航次或多个航段数据统一导入到同一个ODV文件的情况,可以通过站位筛选的方式进行设置:在地图上右键单击选择station filter,在弹出的窗口中(图4.9)可以通过航次/站位信息、时间、区域范围以及设置Meta Data的方式进行筛选。前三种方式比较直观,基本可以实现对不同批次的数据进行分类画图,当然也可以通过Meta Data的方式,比如对不同航段的数据设置一个Leg_flag参数导入到Meta Data中,在Station Filter窗口的Meta Data模块下可以选择数据型,设置Acceptable Range,即可将同一航段的数据筛选出来制图。图4.9 站位筛选设置4.3 不规则采样区域范围的精确选择与保存在对平面分布图进行等值线制图或插值填充的时候,常常会遇到外插的情况,即插值填充的区域超出真实调查采样的区域,这时候我们需要将区域外的数据进行裁剪掉,减少外推可能带来的误导,同时使整个平面分布图更为美观。具体步骤简述如下:在地图上右键单击选择Station Filter,在弹出的窗口中选择Domain模块(图4.10),对于规则的矩形区域可以直接通过设置边界经纬度来定义采样区域,而对于不规则的多边形采样区域,点击右下角的定义多边形Define Polygon,然后会鼠标显示成十字,在地图上逐一依次选择采样区域的边界点,最后双击完成选择,多边形会自动首尾相连闭合,回到Station Filter窗口的Domain模块,点击OK即完成采样区域的设置。4.10 多边形区域设置多边形采样区域的保存有两种途径:- 在地图上右键单击选择Extras -> Export as Graphics Object -> Selection Polygon,在弹出的保存窗口设置保存路径和文件名即可- 在地图上右键单击选择Extras -> Manage Graphics Objects,在弹出的窗口中找到刚才设置好的多边形polygon,选中后点击右侧的Export按键导出即可多边形采样区域的导入:在地图上右键单击选择Station Filter,在弹出窗口的Domain模块(图4.10)右下角点击导入多边形load polygon按键,找到需要导入的多边形采样区域文件打开即可导入。4.4 等深线的叠加如果平面分布图仅以散点形式展示,那么在绘图后图中仍保留与地图中一致的地形(填充或者等深线的形式),此时只需要设置地图中的地形即可,具体操作见“3.4 高分辨率地形显示的自定义设置”。如果平面分布图中对站位数据点进行空间插值填充,那么此时图中的地形会被隐去,防止参数数据的填充与地形填充造成混淆。此时,若需要对采样区域外的空白处进行地形加载,更直观显示数据所处的地形信息,那么可通过以下两种途径加载地形:- 如果有该研究区的外源地形数据文件(*.gob),在图上右键单击,选择Extras -> Add Graphics Object from File ...,在弹出的窗口中找到需要加载的*.gob文件进行加载。- 如果没有现成的外源地形数据文件,需要利用ODV自带或已经加载的高分辨率地形进行显示。目前找到的办法是:将地图中的地形填充改成等深线形式(数据参数与地形均填充的话会造成混淆,建议添加地形信息的话以等深线为宜;修改等深线形式的操作见"3.4 高分辨率地形显示的自定义设置"),然后将地图与图件进行叠加:1)在ODV画布内非地图和图件的空白处右键单击,选择Window Layout,此时会显示地图和图件的编辑网格,在地图和图件窗口的右上角会分别显示“map"或”Window x“等字样;2)在地图或图件上右键单击,选择Move/resize window,对应的图件边框会显示红色,将鼠标移至边框顶点或中间的圆圈处,鼠标会变成双向箭头,此时可以对图件大小进行调整(双击鼠标结束调整!!);当鼠标在图件内部时,鼠标显示为四向箭头,即表明可以拖动整个图件。因此可以将地图和图件窗口调整成相同大小并进行叠加。3)在ODV画布内任意一处右键单击,选择Accept,退出Window Layout设置。Tips:
叠加窗口后,如果需要修改地图或图件的属性,在图件上右键单击选择Properties只能打开最上层的图件属性设置窗口;将鼠标移至图件外,右键单击选择Window Properties,在显示的下拉菜单中选择需要调整的图件,即可打开该图件的属性设置窗口进行设置。五、其它图件的绘制与技巧5.1 站位剖面图的基本绘制方法1)如图4.2所示,在Layout template中提供了站位剖面图(station window)的模板,可通过此方法新建画图窗口。此外,也可通过在window layout界面设置中新添画图窗口(在画布空白处右键单击选择window layout进入画布设置界面,右键单击选择create new window或在现有窗口上选择create overlay window;画布设置界面内窗口的移动或改变大小参见4.4 等深线的叠加中的第2)点,然后通过设置其窗口属性为station window即可(在画图窗口界面右键单击选择Properties,在属性弹窗的Data模块的scope中选择STATION: data of picked stations)。2)在地图上双击需要绘制剖面的站位,在绘图窗口即出现该站位的站位剖面分布。依次点击站位,即累加显示这些站位的剖面分布。3)在绘图窗口右键单击选择Properties,General模块的设置参见”3.1 站位图的基本绘制方法“中的第1)点;4)Data模块中可分别设置x和y轴的参数(图5.1)、属性以及是否逆序,站位图通常将y轴设置为深度。坐标轴的属性设置包括数值范围、刻度分布规律(除线性外,有对数和局部放大分布等)以及刻度和label间隔(默认为automatic)(图5.2)。图5.1 站位剖面图属性设置的Data模块图5.2 坐标轴属性设置5)在Display Style模块(图5.3),设置数据点的标记类型、大小、颜色以及标记之间线的粗细。标记类型虽然有colored dots, sized dots, numbers和arrows四种选项,在站位剖面图中只能默认选择colored dots(即使选择其他类型,都不会有所改变;其他选项对散点图有效)。这里标记颜色可供选择的为ODV默认的32种通用颜色。图5.3 标记设置Tips 1: 站位标记的自定义修改。通过在地图上双击站位添加站位剖面的方法,其标记颜色和符号是自动默认的,修改方法如下:在地图上右键单击选择Manage Pick List -> Edit Pick List,在弹窗Pick List Editor中选中需要修改的站位标记,点Edit对标记类型、大小、颜色以及线条等属性进行更改(图5.4)。图5.4 站位标记设置Tips 2: 对所有站位的所有参数进行overview:在上方菜单栏Collection下拉菜单中选择Create Overview Plots, 即自动对所有参数依据选定的主参数为纵坐标进行画图。如果参数数量太多,在一个画布中容不下,会显示最后一个画布的结果。可通过View -> load view查看其它Overview的结果。5.2 断面图的基本绘制方法1)首先在地图上确定需要绘制的断面,可以是一条直线断面,也可以是折线断面。选取断面方法如下:在地图上右键单击选择Manage section -> define section,此时鼠标的光标变成“十”字,在地图上通过点击鼠标选择断面,双击鼠标结束选择。弹出断面属性设置窗口(图5.5),可设置断面名称、断面绘图时依据的横坐标(从起始点的距离、精度、纬度等)、地形数据选择、断面宽度以及地形填充颜色。其中,如果导入的数据中带有底层深度(Bot. Depth,必须有单位),那么可选用station bottom depth;如果只是绘制该断面上部水层、不涉及到底部地形,可选择No bathymetry;如果需要用地形数据包的地形,选中File并点击Browse选择相应的地形数据文件(*.nc)(图5.6)即可(自主加载的地形数据文件在ODV安装路径的bathymetry文件夹内,地形数据加载的具体步骤参见“3.3 高分辨率地形的加载”)。图5.5 断面属性设置窗口图5.6 地形数据文件2)新建绘图窗口(具体步骤参见“5.1 站位剖面图的基本绘制方法”的第1)点),将窗口属性设置为Section,即在绘图窗口右键单击选择属性,在弹窗Data模块的Scope中选择SECTION。3)选择数据,横坐标选择在断面选择设置时的section coordinate参数(如果当时忘记设置,可在地图上右键单击选择Manage section -> section properties调出断面属性设置窗口)。如果只想看某一层的数据沿断面的变化,可选择其中的某一个参数进行设置;如果是看垂向分布沿断面的变化,纵坐标一般为深度,勾上reverse range即可。z轴选取的是要展示的参数。4)图件要素的设置参见之前介绍的图件基本绘制方法和美化方法,断面数据填充以及等值线的设置办法同“4.1 平面分布图的基本绘制方法”。5)选取的断面需要保存的话,在地图上右键单击选择Manage section -> sava section as,即可将断面信息保存为*.sec文件,方便以后的再次使用。加载已有断面,在地图上右键单击选择Manage section -> load section即可。5.3 时间序列图的基本绘制方法1)在数据导入之前,除导入到metadata的时间数据(时间格式参见“二、数据导入”的第5)点)以外,再添加一列时间参数,可以是把时间转换成数字,或者将时间表示为“yyyy-mm-ddThh:mm:ss"形式(在excel中设置数字形式中选择custom进行自定义设置)且参数名设置为”time_ISO8601",后者在数据导入时会被自动识别。2)新建绘图窗口(具体步骤参见“5.1 站位剖面图的基本绘制方法”的第1)点),将窗口属性设置为Scatter,即在绘图窗口右键单击选择属性,在弹窗Data模块的Scope中选择SCATTER。3)横坐标选用time_ISO8601,即可自动显示时间。如果仅二维展示,则纵坐标选用要展示的参数,为单色显示;如果三维展示,则设置Y轴和Z轴参数;如果展示的是垂向剖面随时间的变化,那么Y轴可设置成深度,勾上reverse range,垂向剖面数据还能进行颜色填充和等值线绘制,具体设置办法同“4.1 平面分布图的基本绘制方法”。4)因为默认的time_ISO8601的时间刻度形式不能更改,若想修改,方法一可通过添加文本的形式添加,方法见“3.6 要素的自定义添加与设置”;方法二参见“附录A:常见问题及解决方案”的A7。5.4 散点图的基本绘制方法从严格意义上讲,时间序列图也是一种散点图;更为广泛地,散点图是绘制两个参数之间的关系。1)新建绘图窗口(具体步骤参见“5.1 站位剖面图的基本绘制方法”的第1)点),将窗口属性设置为Scatter,即在绘图窗口右键单击选择属性,在弹窗Data模块的Scope中选择SCATTER。2)设置坐标轴参数。如果启用Z轴,即标记点通过颜色表示Z轴参数的大小。ODV默认可通过颜色、圆的大小、数字和箭头的形式来展示,且散点间没有连线(站位剖面图可设置数据点之间的连线,但是同一个站位的数据点只能设置成同一颜色)。如果需要突出不同站位之间的特定两个参数之间的关系,也可通过绘制站位剖面图时修改参数设置或者通过extras -> add graphics object -> symbol sets的方式来绘制。3)图件其它要素的设置参见之前介绍的图件基本绘制方法和美化方法。5.5 T-S图中等密线的加载与注意事项T-S图即温度-盐度关系图,是散点图的一种,但因为在水团示踪方面被经常用到,通常称为T-S diagram。在绘制T-S图时,一般为位温(potential temperature)与盐度的关系图,最新的TEOS-10则建议使用保守温度(conservative temperature)和绝对盐度(absolute salinity)。位温、保守温度和绝对盐度可在ODV中根据观测温度、盐度和深度(压强)来计算,具体方法参见“六、新参数与表达式的计算”。绘制T-S图最重要的一点是能自动生成等位密线,此时温度必须是位温或保守温度。设置完成后在绘图窗口右键单击选择extras -> isopycnals,在弹出的窗口设置等位密线的粗细、颜色等。5.6 绘图中常用的其它技巧与问题解决1)同步设置:当在画布中同时绘制多参数图件时,需要保持修改其中一个图件的坐标轴时使得其它图件的坐标轴设置同步变化,只需在ODV属性设置窗口(windows系统用户view -> settings,macOS系统用户odv -> preferences)的View下方的Axis synchronization中勾上”keep axis ranges synchronized“即可。当画布中多个图件的某一项设置需要保持一致,则在设置完成后,在页面左下角勾上“apply to all windows"即可。2)注释格式设置:在设置文本格式时,常用到的上标、下标以及希腊字母符号的设置如图5.7和图5.8所示。例如,”CO2“中的”2“需要下标,表示为”CO~_2“;”m s-1"中的“-1”需要上标,表示为“m s~^-~^1",注意这里的每一个上标字符前都需要加”~^“;”5‰“表示为”5~%“。"△DIC”需要用到希腊字母"△”,首先在图5.8中找到与“△”对应的拉丁字母“D”,结合图5.7中希腊字母与拉丁字母格式转换的要求,即可表示为“~$D~#DIC"。注意:”~$“默认将该符号后面的字母全部转换为希腊字母,因此跟在希腊字母后面正常表示的拉丁字母需要加“~#“将格式转换回来。此外,在希腊字母表示时需要区分大小写。图5.7 文本上下标及字符格式转换设置(摘自ODV的User‘s Guide)图5.8 字符格式转换中希腊字母与拉丁字母对应关系(摘自ODV的User&amp;amp;amp;amp;amp;amp;#39;s Guide)3)导入单位符号异常问题的解决办法:将*.txt或*.csv文件中的数据导入到ODV中时,有时候出现参数单位符号为乱码的情况,此时可以检查原始数据文件的编码格式是否保存为UTF-8编码格式。如果不是,建议保存为编码为UTF-8格式的csv文件即可。六、根据已有参数计算新参数ODV提供了根据已有参数计算得到新参数的方法,主要包括碳酸盐系统(碱度、DIC、pH、pCO2、fCO2、碳酸钙饱和度Ω、Revelle factor以及碳酸盐系统各组分浓度)、气体(表观耗氧量AOU、饱和溶氧以及甲烷CH4、CFC-16和SF6相关参数)、Metadata、EOS80和TEOS-10版本的物理参数、时间参数等。此外,还能通过手动输入表达式根据已有参数计算得到新参数。6.1 利用ODV自带公式计算新参数通过选择顶边菜单栏View -> Derived variables,弹出定义新参数设置窗口,如图6.1所示。在窗口右侧的Choices模块中选择需要计算的新参数,选中参数后点击右下角的Add,根据指示选择计算需要的已有参数,选择结束后会在窗口左侧的Already defined模块中显示新参数,点击OK结束,在作图选择参数时可在下拉参数菜单中找到新定义的参数,同时也会在画布右侧的Sample模块最下方显示新定义的参数及其数值。图6.1 定义新参数设置窗口6.2 构建表达式计算新参数同样调出定义新参数设置窗口,在Choices模块中选择Expressions, Derivatives, Integrals下面的Expression,弹出表达式编辑窗口,如图6.2所示。1)设置表达式计算得到参数的名称、单位以及小数点位数;2)选择要用到的已有参数,通过依次选中参数然后点击”<<“按钮添加到Defined模块中备用,ODV会自动给每个添加进来的已定义参数设置序号,方便在编辑表达式时使用。3)编辑表达式时,直接输入到Expression in Postfix Notation模块的表达式与我们常用的嵌入式表达式不同,例如我们将新参数new_variable定义为“DO - S*((T+273.15)0.5+(T+273.15)^2)",则嵌入式表达式为”#3 - #2*((#1+273.15)*0.5+(#1+273.15)^2)“,而Postfix Notation的表达式为”#3 #1 273.15 + 0.5 * #1 273.15 + 2 ** + #2 * -“。如果不熟悉postfix格式的表达式,可以点击下方的Enter infix expression在弹窗中输入嵌入式表达式,ODV会自动将其转换成postfix格式(如图6.2所示)。如果自己编辑的postfix格式的表达式不确定是否正确,可点击下方的Validate按钮进行检验。最后点击OK即可将新定义的参数添加到定义新参数编辑窗口的Defined模块中。4)对新定义的参数的修改,选中要修改的参数,点击下方的Edit按钮可以对设置进行修改。图6.2 表达式编辑窗口附录A:常见问题及解决方案A1:csv或txt文件无法正常导入可能的解决方案:检查是否包含除metadata以外的参数。如果没有,则添加任意metadata以外参数即可。metadata参数见附图A1.附图A1. ODV中的metadata参数(摘自ODV的User‘s Guide)A2:如何根据实测站位水深制作等深线gob文件以用于加载到平面图中?基于ODV的解决方案:将实测站位水深在导入到ODV过程中添加到Variable模块(不同于一般情况,将实测站位水深作为Bot. Depth添加到metadata模块)导入成功后,将实测站位水深数据生成为isosurface variables,对其进行平面作图,并进行DIVA插值填充,绘制等深线绘制完成后,鼠标移至填充区域,右键单击选择Extras -> Export as Graphics Object -> Contour Lines,保存为*.gob文件生成的*.gob文件在其它参数平面图中,鼠标右键单击选择Extras -> Add Graphics Object from file -> GOB file即可其它可能的解决方案 :借助其它软件将水深数据生成*.cdt 或.shp文件,按照上述解决方案的最后一步导入到ODV平面图中A3:ODV画布内图件无法正常缩放Windows系统用户通过View -> Settings或MacOS系统用户通过odv -> Preferences弹窗,在View -> Canvas Size页面,点击fit to screen即可A4:如何在地图中显示河流?ODV一般只能显示相对大型的河流,一些区域性的小河可能显示不了。河流的显示方法:在地图上右键选择properties,在弹出窗口选择layers模块,如果勾选了automatic selection,就是ODV自带的地形数据,那么在下方勾选Lakes and rivers即可,如果没有勾选automatic selection而是选用后期加载的地形数据,例如ETOPO1_2min,在layer_selection中选中post-topography,点击compose,在弹出的对话框中从available中依次选中不同规模的Rivers,在右侧设置河流的线和填充属性,然后一定要点击<<键,确保设置的河流出现在selected中,最后点击OK即可。如果这两种方法都不能显示你想要的河流,那么可能本身该河流数据不包含在所选择的地形数据中A5:如何导出ODV插值后的数值?对平面分布图或断面剖面图进行空间插值后,在ODV窗口最上边菜单栏点击Export -> window data,选择对应的窗口,在弹出窗口选择保存路径和设置文件名,点击确定后在弹出窗口Export Window Data选择导出原有参数数据点及其位置上由空间插值导致的偏差‘Export data values and gridding misfits at data positions’或导出插值后的网格点数据‘Export gridded field values and "poor man's errors"’,并选择数据间分隔符和勾选导出参数的labels以及missing Z valuesA6:手动添加的地形数据在断面剖面图中无法显示如果是windows系统用户,将ODV安装在D盘等非C盘,需要将从别处拷贝或下载的地形数据bathymetry文件拷贝到ODV安装盘的ODV文件夹里面才有效,切记必须同时包含.nc文件和.settings文件A7:时间序列图中时间轴刻度值的设置通过ODV画布最上方菜单栏的view -> Derived variables,在弹出的窗口中右侧选择Times下拉菜单中的时间格式,点击右下角的Add,选择时间参数,即可生成具有特定时间格式的时间参数,用于画图时时间轴的参数选择即可。A8:不同的ODV数据文件,如何通过设置模板画一样的图?或数据更新后,如何在新的ODV文件中快速画原来设置好参数的图?将原来ODV文件中画好的图通过View -> Save View as保存,然后再新的ODV数据文件中通过View -> Load View打开,根据需求稍作调整即可A9:如何更改地图中陆地的颜色?将鼠标移至地图上,右键单击Properties,在属性窗口选择Layers,勾掉automatic selection,选择地形数据包,然后在下面Layer selection的框中选中coastlines,点击右侧的compose,在弹出的窗口的available下面选中world,然后在右侧设置线条和填充颜色,选择完毕后一定要点击“<<”的按键,保证设置的内容更新到selected框中,最后点击OK即可* 更新说明:(1)使用ODV制图用于文章发表等,请注明引用;(2)关于高分辨率地形通过外源数据加载和cmocean的加载,不是将对应文件放置到ODV的安装包目录下,而是应该放置在ODV用户文件夹下面,用户文件夹路径可通过windows: view -> settings或macOS: odv -> preferences打开设置窗口,在system下面的user directory中可以找到;图3.1。(3)Scientific Colour Maps适用于ODV的配色方案已提供。(4)基本的ODV绘图方法与技巧介绍已完结,之后有新的发现会继续补充更新。* 有ODV操作问题或者文中操作有不能实现或错误的地方可以留言,欢迎批评指正,谢谢!* 转载请联系我并注明出处,仅用于学术交流,谢谢合作!
本章内容提要:列表及操作元组及操作字典及操作集合简介第2章介绍了数字(整数、浮点数)、逻辑值和字符串等Python内置的基本数据类型。在实际的操作中,仅仅依赖它们很难高效地完成复杂的数据处理任务。基于对基本数据类型的构建,Python拓展出列表、元组、字典与集合等更为实用的数据结构,以简化程序的编写与任务的实现。这些数据结构内置于Python,是数据分析经常要操作的对象。3.1 列表列表(list)是Python中最常用的内置类型之一,是处理一组有序项目的数据结构,或者说,是一个有序对象的集合。通俗地理解,列表即序列,它是一系列数值的序列。在前文介绍的字符串中,字符串包含的值是一个个字符。而在列表中,值可以是任意类型。列表的值一般也称为列表的元素,通过英文逗号分隔,并包含在方括号内。3.1.1 列表的创建下面创建一个简单的列表,存储英文中的5个元音字母:In [1]: vowels = ['a', 'e', 'i', 'o', 'u']
In [2]: vowels
Out[2]: ['a', 'e', 'i', 'o', 'u']我们可以不添加任何元素来初始化一个列表:In [3]: array_init = []
In [4]: array_init
Out[4]: []如果要提取列表中的元素,使用索引是一种方法,将索引值写在变量名后的方括号内,如提取列表vowels中的i:In [5]: vowels[2]
Out[5]: 'i'方括号内填入的是2,而不是3。这与Python的索引机制有关—— Python的索引是从0开始的(当然也有从1开始索引的语言,比如数据分析中也非常流行的R语言)。因此,列表vowels元素与其索引之间有以下对应关系:a e i o u
0 1 2 3 4列表的元素可以是任意类型,因此列表可以嵌套列表。例如,用以下列表来依次表示两个长方形的名称、面积与相应的长和宽:In [7]: rectangle = ['长方形1', 20, [4, 5], '长方形2', 16, [4, 4]]
In [8]: rectangle
Out[8]: ['长方形1', 20, [4, 5], '长方形2', 16, [4, 4]]如果列表太长,不方便直接观察列表的长度,那么可以利用len()函数进行计算。In [9]: len(rectangle)
Out[9]: 6结果显示rectangle长度为6,我们可以使用索引值0~5提取rectangle的元素。再次注意,Python索引值是从0开始的,如果使用的索引值超出界限,Python会报错,提示我们使用的列表索引超出范围。In [10]: rectangle[6]
---------------------------------------------------------------------------
IndexError
Traceback (most recent call last)
<ipython-input-10-6e16763c0048> in <module>()
----> 1 rectangle[6]
IndexError: list index out of range除了从头创建一个列表,也可以使用list()函数将其他数据类型转换为列表,如下面的字符串:In [17]: aseq = "atggctaggc"
In [18]: list(aseq)
Out[18]: ['a', 't', 'g', 'g', 'c', 't', 'a', 'g', 'g', 'c']3.1.2 修改列表元素和字符串不同,列表是可以修改的,只需对指定的列表元素重新赋值即可。例如,用一个列表存储10以内的奇数:In [11]: odd_numbers = [1, 3, 5, 7, 8]即使发现最后一个元素写错了,也不需要像下面这样重新创建列表。In [12]: odd_numbers = [1, 3, 5, 7, 9]我们不需要重新输入创建一个新的列表来纠正之前错误的输入,只需要修改写错的元素,即利用索引对错误的元素重新赋值。In [13]: odd_numbers = [1, 3, 5, 7, 8]
In [14]: odd_numbers[4] = 9
In [15]: odd_numbers
Out[15]: [1, 3, 5, 7, 9]除了使用自然数进行索引元素,还可以使用负整数进行反向索引,比如odd_numbers[-1]也对应着9:In [16]: odd_numbers[-1]
Out[16]: 9我们依旧可以用之前的列表vowels来表示列表元素与反向索引之间的对应关系,如下: a
e
i
o
u
-5
-4
-3
-2
-13.1.3 遍历列表想象一下,如果列表元素非常多,而我们想要对列表中的每一个元素进行操作或变换,难道要一个一个利用索引取出,然后修改吗?逐一访问列表的元素称为遍历列表。这里需要初步借助第4章介绍的循环来解决类似的问题。循环的作用在于将单一枯燥的重复性工作交给机器去实现,而用户只需要关注去掉循环的操作本身。最常用的循环结构是for循环。如果需要逐一打印10以内的奇数,我们不需要逐步使用print()函数打印列表的每一个元素。print(odd_numbers[0])
print(odd_numbers[1])
print(odd_numbers[2])
print(odd_numbers[3])
print(odd_numbers[4])只需要两行代码就可以实现列表的遍历,如下所示:In [24]: for i in odd_numbers:
print(i)
1
3
5
7
9这里列表odd_numbers中元素的值会逐个传给i,然后通过print()函数将i的值输出打印。使用循环除了使代码更清晰简洁外,另一个好处是用户不需要知道列表有多长!既然for循环可以遍历列表中所有的元素,那么如果元素是一个列表,它会对这个列表接着遍历吗?假设创建一个列表存储小明、小红、小蓝3个人跳远的成绩记录,如下:In [26]: nested_list = ['记录', 3, ['小明', '小红', '小蓝'], [2.30, 2.41, 2.33]]使用for循环是将该列表中的所有元素一个一个输出,还是会输出其他的结果呢?In [27]: for i in nested_list:
...:
print(i)
...:
记录
3
['小明', '小红', '小蓝']
[2.3, 2.41, 2.33]结果显示,for循环并没有将列表的所有元素单个传入变量i,而是将列表最外面一层的元素传入了变量i。打个比方,简单的列表像一层洋葱,而嵌套了列表的列表相当于多层洋葱,for循环只负责剥开一层。因此,如果想剥开例子中的“两层洋葱”—— nested_list,我们需要使用两次for循环。for循环的操作和使用在第4章会详细介绍。3.1.4 列表操作符列表操作符用于便利地操作列表,使用它们如同使用数值的加、减、乘、除一样简单。1.加号加号 + 不仅能用于数字相加、字符连接,还能用于列表的拼接。In [28]: a = [1, 2, 3]
In [29]: b = [4, 5, 6]
In [30]: a + b
Out[30]: [1, 2, 3, 4, 5, 6]a + b的结果是将列表b中的元素拼接到列表a的后面,生成了一个新的列表。如果两个列表是不同的数据类型,还能拼接吗?In [31]: b = [4, 5, '6']
In [32]: a + b
Out[32]: [1, 2, 3, 4, 5, '6']代码运行结果说明是可以的,列表包容万物,而含不同数据类型的列表拼接只是将它们放到了一起,并没有其他特殊的操作。2.星号星号 * 操作符可以将列表重复指定的次数,如下所示:In [33]: a * 5
Out[33]: [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]3.1.5 列表切片除了上一节提到的 + 操作符与 * 操作符,冒号 : 操作符可以对列表执行切片操作。切片操作是利用冒号操作符进行取子集的过程。因为该操作符经常使用,所以单列一节进行介绍。例如,如果存在包含7个字母的列表如下:In [34]: letters7 = ['a', 'b', 'c', 'd', 'e', 'f', 'g']如果只想要a、b、c、d这4个字母,那么切片操作如下:In [37]: you_want = letters7[0:4]
In [38]: you_want
Out[38]: ['a', 'b', 'c', 'd']列表索引规则是start:stop:step,其中,stop值不被包含在内(即区间前闭后开)。上面代码中,start对应0(再次提醒Python索引从0开始),stop对应4,而step默认为1,可以省略。理解了切片的规则,我们就可以知道下面的操作会得到一样的结果。In [39]: letters7[0:4:1]
Out[39]: ['a', 'b', 'c', 'd']索引的起始位置也可以省略,默认从0开始。In [40]: letters7[:4]
Out[40]: ['a', 'b', 'c', 'd']索引的终止位置也可以省略,默认为列表长度,也就是到最后一个元素。In [41]: letters7[:7]
Out[41]: ['a', 'b', 'c', 'd', 'e', 'f', 'g']
In [42]: letters7[4:]
Out[42]: ['e', 'f', 'g']注意,加 : 操作符与不加是不同的。加 : 操作符,结果返回的是一个列表,而不加返回的是元素本身。In [43]: letters7[-1]
Out[43]: 'g'
In [44]: letters7[-1:]
Out[44]: ['g']在理解了上面操作的基础上,理解下面的操作结果也顺理成章。In [45]: letters7[::1]
Out[45]: ['a', 'b', 'c', 'd', 'e', 'f', 'g']
In [46]: letters7[::2]
Out[46]: ['a', 'c', 'e', 'g']步长还可以取负整数,代表逆序切片。In [47]: letters7[::-1]
Out[47]: ['g', 'f', 'e', 'd', 'c', 'b', 'a']
In [48]: letters7[::-2]
Out[48]: ['g', 'e', 'c', 'a']另外,切片运算符放到赋值语句等号左边时可以对多个元素进行更新。In [49]: letters7[0:2] = ['h', 'i']
In [50]: letters7
Out[50]: ['h', 'i', 'c', 'd', 'e', 'f', 'g']注意,左右两边可以不等长。In [51]: letters7[0:2] = ['a']
In [52]: letters7
Out[52]: ['a', 'c', 'd', 'e', 'f', 'g']
In [53]: letters7[0:1] = ['a', 'b']
In [54]: letters7
Out[54]: ['a', 'b', 'c', 'd', 'e', 'f', 'g']如果是单个元素,等号右侧也可以不加方括号。In [55]: letters7[0:2] = 'h'
In [56]: letters7
Out[56]: ['h', 'c', 'd', 'e', 'f', 'g']3.1.6 列表方法、函数与操作Python为列表提供了很多方法,用来简化列表的各项常用操作。常用操作包括添加元素、删除元素、插入元素等。注意,当下文提及方法时,一般指在变量名后加点号然后加函数。例如,list.append()指对列表list使用append()方法。1.添加元素Python中有3种方法可以为列表添加元素,分别是append()、insert()和extend()。(1)append(element):将元素element添加到列表的末尾。In [59]: example_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
In [60]: example_list.append(11)
In [61]: example_list
Out[61]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11](2)insert(position, element):将元素element插入列表指定position位置。In [62]: example_list.insert(2, 12)
In [63]: example_list
Out[63]: [1, 2, 12, 3, 4, 5, 6, 7, 8, 9, 10, 11](3)extend(list):使用另一个列表作参数,然后把所有的元素添加到一个列表上。In [64]: example_list.extend([13,14])
In [65]: example_list
Out[65]: [1, 2, 12, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14]2.删除元素同样地,Python也有3种方法删除列表中的元素。(1)pop([index]):移除索引位置index的元素并返回它的值,如果没有参数,则默认删除和返回最后一个。In [67]: example_list.pop()
Out[67]: 14
In [68]: example_list.pop(2)
Out[68]: 12(2)remove(element):移除参数中指定的元素element,如果存在多个同样的值,则移除最左边的。不同于pop(),这个方法不返回任何值。In [69]: example_list.remove(13)
In [70]: example_list
Out[70]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11](3)另一种方式是使用del命令,del list[0]类似于list.pop(0),但前者不会返回被删除的元素。In [71]: del example_list[10]
In [72]: example_list
Out[72]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]除了上面提到的3种方法,另有clear()方法可以清洗列表,它会清空列表中的所有元素。In [73]: example_list.clear()
In [74]: example_list
Out[74]: []3.列表排序当把数值数据存储在列表后,一个常见的需求是对列表中的值进行排序,利用sort()方法可以实现。In [78]: a = [3, 1, 2, 5, 4, 6]
In [79]: a.sort()
In [80]: a
Out[80]: [1, 2, 3, 4, 5, 6]可以看到,使用sort()方法后,列表本身被改变了。如果不想改变原始列表,可以使用sorted()函数,并把结果赋值给新的变量。In [81]: nums = [-1, 34, 0.2, -4, 309]
In [82]: nums_desc = sorted(nums, reverse=True)
In [83]: nums
Out[83]: [-1, 34, 0.2, -4, 309]
In [84]: nums_desc
Out[84]: [309, 34, 0.2, -1, -4]reverse()方法可以将列表按位置翻转。In [90]: nums
Out[90]: [1, 2, 2, 2, 3, 3, 4, 5]
In [91]: nums.reverse()
In [92]: nums
Out[92]: [5, 4, 3, 3, 2, 2, 2, 1]4.简单统计min()与max()函数可以计算列表最小值与最大值。In [85]: min(nums)
Out[85]: -4
In [86]: max(nums)
Out[86]: 309如果要对出现相同元素计数,可以使用count()方法。In [87]: nums = [1, 2, 2, 2, 3, 3, 4, 5]
In [88]: nums.count(2)
Out[88]: 3
In [89]: nums.count(3)
Out[89]: 2sum()函数可以对数值列表求和。In [93]: sum(nums)
Out[93]: 225.逻辑判断如果需要查看列表中是否存在某个元素,可以使用关键字in,结果返回的是逻辑值。In [76]: 4 in example_list
Out[76]: False
In [77]: 3 in example_list
Out[77]: Trueall()与any()函数用于逻辑值列表,all()判别列表所有值是否都为真,全真时返回True,否则返回False;any()用于判别只要任一元素为真,则返回True,否则返回False。In [94]: conditions = [True, False, True]
In [95]: all(conditions)
Out[95]: False
In [96]: any(conditions)
Out[96]: True如果要比较两个列表是否一致,则可以直接使用两个等号进行逻辑判断。In [97]: a = [1, 2, 3, 4]
In [98]: a == [1, 2, 3, 5]
Out[98]: False
In [99]: a == [1, 3, 2, 4]
Out[99]: False
In [100]: a == [1, 2, 3, 4]
Out[100]: True6.最常见操作方法汇总上面介绍了大量的列表操作、函数与方法,但实际上可用的远不止这些。对Python有深入了解后,我们可以自己创建操作列表的方法和函数。表3-1中列出了常见的操作方法。3.1.7 列表与字符串字符串是一系列字符的序列,而列表是一系列值的序列,但一个由字符组成的列表是不同于字符串的。要把一个字符串转换成字符列表,可以用list()函数。下例是将字符串转换为字符列表:In [101]: s = 'interactive Python'
In [102]: t = list(s)
In [103]: t
Out[103]:
['i',
'n',
't',
'e',
'r',
'a',
'c',
't',
'i',
'v',
'e',
' ',
'P',
'y',
't',
'h',
'o',
'n']在上面的代码中,list()函数将一个字符串分开成一个个字符(字母)。如果要把字符串切分成一个个单词,可以使用split()方法,如下所示:In [104]: s.split()
Out[104]: ['interactive', 'Python']注意,方法中有一个可选的参数是定界符,用于确定单词边界。下例用短横线作为定界符来拆分两个单词:In [105]: s = 'interactive-Python'
In [107]: s.split('-')
Out[107]: ['interactive', 'Python']另一个方法join()的功能与split()方法的功能相反,它接收一个字符串列表,然后把所有元素拼接到一起作为字符串。join()是一个字符串方法,所以必须把join()放到定界符后面来调用,并且传递一个列表作为参数。In [108]: t = ['我','是', '谁', '?']
In [109]: ''.join(t)
Out[109]: '我是谁?'注意,上面代码中的定界符是一个空格字符。3.1.8 列表对象与值请思考:下面对象a与b是同一个对象吗?In [4]: a = 'banana'
In [5]: b = 'banana'如果把对象看作篮子,内容banana看作篮子里的鸡蛋。现在需要判断的是,变量名a和b是同一个篮子的两个便签(鸡蛋只有一个),还是两个不同篮子(每一个篮子都有一个鸡蛋)的便签?使用is操作符,可以得到答案。In [6]: a is b
Out[6]: True从上面的代码运行结果来看,答案是第一种情况:Python只创建了一个字符串对象,内容为banana,a和b都是这个对象的便签。另外,可以使用id()函数提取对象的唯一标识符。这就像居民身份证一样,虽然同一个人可能会有不同的称呼,但身份证号码只有一个。In [10]: id(a)
Out[10]: 1691582590008
In [11]: id(b)
Out[11]: 1691582590008从结果中可见,a和b确实是完全相同的。那么,如果改变a,那么b也会随之改变吗?In [12]: a = "orange"
In [13]: b
Out[13]: 'banana'结果是不会。实际上,Python对象是它指向的内容,变量名a和b本身只是一个方便使用的标签,所以当我们将另一个字符串赋值给变量a时,Python实际上是先创建了一个字符串对象,内容是orange,然后给这个对象打上标签a。如果创建两个列表,尽管它们的内容相同,但它们也是不同的对象,下面的代码运行结果可以验证这一点。In [14]: a = [1, 2, 3]
In [15]: b = [1, 2, 3]
In [16]: a is b
Out[16]: False
In [17]: id(a)
Out[17]: 1691581888264
In [18]: id(b)
Out[18]: 1691582794120在这个情况下,可以说两个列表是相等的,因为它们有相同的元素,但不是同一个列表,因为它们并不是同一个对象。如果两个对象是同一个对象,那么它们必然是相等的;但如果它们相等,却未必是同一个对象。注意,如果这里的b不是重新创建,而是将a赋值给b,那么a和b就是完全相同的,因为它们指向同一个列表对象。In [19]: b = a
In [20]: a is b
Out[20]: True
In [21]: id(b)
Out[21]: 1691581888264因此,我们尽量不要对Python的列表进行e=f=e=c=a这样的赋值操作,一旦修改了某一个元素,其他变量全部会跟着改变!In [22]: e = a
In [23]: e
Out[23]: [1, 2, 3]
In [24]: a
Out[24]: [1, 2, 3]
In [25]: a[1] = 4
In [26]: e
Out[26]: [1, 4, 3]到这里,本章一一介绍了Python列表的基础知识和相应操作。本章的大部分内容是在讲解列表,列表不仅是Python最核心的概念和数据结构,也是理解其他基础数据结构的桥梁。掌握好了列表,读者对本章接下来介绍的数据结构都可以触类旁通,其使用和操作方法大同小异。重要的差异会给出提示和强调,读者需要留心注意。3.2 元组元组(tuple)就是不可更改的列表,一旦创建,便不可更改。除了表示的方式有点不一样、元组的元素不可更改,元组的其他特性与列表基本一致。3.2.1 元组的创建In [1]: a_tuple = (1, 2, 3)
In [2]: a_list = [1, 2, 3]上面代码分别创建了一个元组和列表,可以清晰地看到它们定义的差别所在。其实元组的语法是一系列用逗号分隔的值,也就是说括号是可以省略的。In [6]: another_tuple = 1,2,3
In [7]: type(another_tuple)
Out[7]: tuple作为初学者,创建元组时尽量使用括号,这样在书写和查看代码时可以非常清楚地区分什么是列表、什么是元组。Python中常见的数据类型在表示上都有着非常鲜明的特点,这可以帮助读者构建优良的代码。当创建的元组只有一个元素时,需要特别注意:元组中的元素后需要一个逗号。请看下面的代码:In [8]: 1
Out[8]: 1
In [9]: (1)
Out[9]: 1
In [10]: 1,
Out[10]: (1,)
In [11]: (1,)
Out[11]: (1,)前两个命令创建的都是数字1,后两个命令创建的才是元组,包含元素数字1。除了使用逗号分隔创建元组,创建元组的另一种方式是使用tuple()函数。如果参数为一个序列(比如字符串、列表或者元组),结果就会得到一个以该序列元素组成的元组。In [14]: tuple("Python")
Out[14]: ('P', 'y', 't', 'h', 'o', 'n')
In [15]: tuple(["I", "am", ["learning", "Python"]])
Out[15]: ('I', 'am', ['learning', 'Python'])3.2.2 元组操作适用于列表的操作符和方法基本也适用于元组。1.操作符代码如下:In [16]: ('a',) + ('b',)
Out[16]: ('a', 'b')
In [17]: ('a',) * 3
Out[17]: ('a', 'a', 'a')2.切片代码如下:In [18]: pythonName = tuple("Python")
In [19]: pythonName
Out[19]: ('P', 'y', 't', 'h', 'o', 'n')
In [20]: pythonName[0]
Out[20]: 'P'
In [21]: pythonName[0:3]
Out[21]: ('P', 'y', 't')
In [22]: pythonName[3:]
Out[22]: ('h', 'o', 'n')3.修改元组是不可修改的,所以不能使用append()和pop()等方法对元素进行添加、删除、修改等操作。In [23]: pythonName[0] = 'p'
---------------------------------------------------------------------------
TypeError
Traceback (most recent call last)
<ipython-input-23-19ded1757eee> in <module>()
----> 1 pythonName[0] = 'p'
TypeError: 'tuple' object does not support item assignment但可以用另一个元组来替换已有的元组。In [24]: newName = ('p',) + pythonName[1:]
In [25]: newName
Out[25]: ('p', 'y', 't', 'h', 'o', 'n')4.变量值交换利用中间变量对变量的值进行交换是一个常见的操作。例如,要交换变量a和b的值,我们一般会采用如下策略:# a和b是已经创建的变量,t是一个临时变量
t = a
a = b
b = t有了元组,我们就可以使用下面一行代码简化这一过程。a, b = b, a3.2.3 元组与列表的区别看到这里,读者可能会产生疑问:元组能做的事情列表好像都能做,列表还没有元组这么多的约束,那么只用列表不是更好吗?元组相比于列表的优点之一是可以使代码更安全,特别是与数据有关的,元组不能修改的属性看起来是一层灵活性限制,其实也是一层安全性的保障,而且这个属性让元组像一个坐标系统(中学数学也用括号来填入坐标,并用逗号分隔),比如3个元素c(x,y,z),所以它广泛用于参数的传递。关于参数传递,本书在第5章会详述。另外,元组的一个隐形的优点是它比列表占用的内存更少,这在大数据计算时需要考量。3.3 字典字典的含义和表示都与其语义相似,就像我们小时候查找汉字,可以通过拼音字母(或笔画)进行检索。我们可以自己定义Python中的字典名字,然后通过这个名字查找到对应的数值。其中的名字叫作“键”,对应的数值简称“值”,所以字典也称“键值对”。需要注意的是,字典没有顺序一说,所有的值仅能用键获取。简而言之,字典被看作无序的键值对或有名字的元素列表。3.3.1 字典的创建与使用下面代码使用字典存储了3个人的体重数据。In [5]: weight = {'小红':65, '小明':45, '我':75}字典的内容放在花括号内,键值对以英文冒号连接,不同的键值对以英文逗号隔开。下面代码用于查看对字典的打印输出:In [6]: weight
Out[6]: {'小明': 45, '小红': 65, '我': 75}从结果中可以看到,输出的顺序与键入的顺序是有差别的(也有可能相同)。有了字典,我们可以用比列表更简单和直观地提取对应内容的数据。例如,可以使用下面的代码获取小明的体重。In [7]: weight['小明']
Out[7]: 45既然字典有键与值的区分,那么该如何获取键与值的内容呢?为此Python提供了两个方法,分别是keys()和values()。In [8]: weight.keys()
Out[8]: dict_keys(['小红', '小明', '我'])
In [9]: weight.values()
Out[9]: dict_values([65, 45, 75])因为字典需要唯一的键去提取正确的内容(值),所以并不是所有的对象都可以用作键。只有不能改变的元组、数字、字符串等能作为键。如果要初始化字典,类似于列表使用符号[]、元组使用符号()、字典使用符号{}。In [10]: int_dict = {}
In [11]: int_dict
Out[11]: {}除了重新创建字典,还可以把从其他数据类型转换为字典。例如,下面有一个存储了RGB16进制的列表,我们使用dict()函数将其转换为字典。In [13]: rgb = [('red', 'ff0000'), ('green', '00ff00'), ('blue', '0000ff')]
In [14]: dict(rgb)
Out[14]: {'blue': '0000ff', 'green': '00ff00', 'red': 'ff0000'}此外,还可以以传递参数给dict()函数的方式创建字典。下面代码创建的字典与上面代码创建的字典完全相同。In [15]: dict(red='ff0000',green='00ff00', blue='0000ff')
Out[15]: {'blue': '0000ff', 'green': '00ff00', 'red': 'ff0000'}如果需要不断地往字典中添加键值,那么要先初始化字典,然后使用赋值的方式添加键值对。In [16]: rgb = {}
In [17]: rgb['red'] = 'ff0000'
In [18]: rgb['green'] = '00ff00'
In [19]: rgb['blue'] = '0000ff'
In [20]: rgb
Out[20]: {'blue': '0000ff', 'green': '00ff00', 'red': 'ff0000'}3.3.2 字典操作一些常见的函数和方法都可以用在字典上。例如,提取字典长度。In [21]: len(rgb)
Out[21]: 3使用pop()方法可以从字典中删除某个值,并返回该值。注意,需要指明键。In [22]: rgb.pop()
---------------------------------------------------------------------------
TypeError
Traceback (most recent call last)
<ipython-input-22-1654217e28c5> in <module>()
----> 1 rgb.pop()
TypeError: pop expected at least 1 arguments, got 0
In [23]: rgb.pop('blue')
Out[23]: '0000ff'
In [24]: rgb
Out[24]: {'green': '00ff00', 'red': 'ff0000'}使用del关键字可以删除字典。In [25]: del rgb
In [26]: rgb
---------------------------------------------------------------------------
NameError
Traceback (most recent call last)
<ipython-input-26-d412e57c3c38> in <module>()
----> 1 rgb
NameError: name 'rgb' is not defined使用get()方法可以无意外地获取字典值,它需要提供两个参数,除了键,还需要指定如果查找不到应当返回的信息。In [28]: rgb.get('red', '键不存在')
Out[28]: 'ff0000'
In [29]: rgb.get('yellow', '键不存在')
Out[29]: '键不存在'如果不改变字典的顺序,可以使用collections模块的OrderedDict()函数。下面的代码将之前创建的字典rgb转换为了有序字典,还给出了一个新的创建示例,可以发现列表输出的顺序确实没有改变。In [32]: from collections import OrderedDict
In [33]: OrderedDict(rgb)
Out[33]: OrderedDict([('red', 'ff0000'), ('green', '00ff00'), ('blue', '0000ff')])
In [35]: order_dict = OrderedDict()
In [36]: order_dict['a'] = 1
In [37]: order_dict['b'] = 2
In [38]: order_dict['c'] = 3
In [39]: order_dict
Out[39]: OrderedDict([('a', 1), ('b', 2), ('c', 3)])3.4 集合集合是无序的对象集,它和字典一样使用花括号,但没有键值对的概念。集合属于可变的数据类型,一般用于保持序列的唯一性—— 也就是同样的元素仅出现一次。3.4.1 集合的创建在使用集合时一定要注意集合的“无序”和“唯一”两个特点,避免出错。在下面代码中,当集合出现不唯一的字符时,创建的集合中只会保存一个。In [40]: a_set = {1, 2, 3, 4, 5, 5, 4}
In [41]: a_set
Out[41]: {1, 2, 3, 4, 5}既然集合与字典都使用花括号,那么如果要初始化一个空集合,该怎么办?还能用花括号吗?In [42]: a_set = {}
In [43]: a_set.add(1)
---------------------------------------------------------------------------
AttributeError
Traceback (most recent call last)
<ipython-input-43-2a4eeb394ac5> in <module>()
----> 1 a_set.add(1)
AttributeError: 'dict' object has no attribute 'add'结果显示报错,信息显示字典没有add属性,说明花括号仅能初始化字典。集合对应的函数是set(),因而我们必须使用它初始化或将其他数据类型转换为字典。In [44]: a_set = set()
In [45]: a_set.add(1)
In [46]: a_set
Out[46]: {1}3.4.2 集合操作集合的常见用处是进行集合操作,这涉及3个基本方面:合集(并集)、交集和差集。1.合集合集使用union()方法如下。In [47]: a_set = set([1, 2, 3, 4, 5])
In [48]: b_set = set([4, 5, 6, 7, 8])
In [49]: a_set
Out[49]: {1, 2, 3, 4, 5}
In [50]: b_set
Out[50]: {4, 5, 6, 7, 8}
In [51]: a_set.union(b_set)
Out[51]: {1, 2, 3, 4, 5, 6, 7, 8}2.交集交集使用intersection()方法如下。In [52]: a_set.intersection(b_set)
Out[52]: {4, 5}3.差集差集使用difference()方法如下。In [53]: a_set.difference(b_set)
Out[53]: {1, 2, 3}3.4.3 冰冻集上一节提到,集合是可变的数据类型。在实际的数据分析中,有时希望集合存储的数据不能改变,以防信息被恶意篡改或者出现其他数据失真的情况。冰冻集(frozenset)提供了集合的不可变版本,它的内容不能改变,因此不存在add()与remove()方法。frozenset()函数可以将输入的迭代对象转换为冰冻集。In [1]: fs = frozenset(['a', 'b'])
In [2]: fs
Out[2]: frozenset({'a', 'b'})
In [3]: fs.remove('a')
---------------------------------------------------------------------------
AttributeError
Traceback (most recent call last)
<ipython-input-3-b55f44b7e2c9> in <module>()
----> 1 fs.remove('a')
AttributeError: 'frozenset' object has no attribute 'remove'
In [4]: fs.add('c')
---------------------------------------------------------------------------
AttributeError
Traceback (most recent call last)
<ipython-input-4-34531eab3bc0> in <module>()
----> 1 fs.add('c')
AttributeError: 'frozenset' object has no attribute 'add'冰冻集由于是不可变对象,所以可以用作字典的键。3.5 章末小结本章详细介绍了Python内置的4个重要基本数据结构,分别是列表、元组、字典和集合。其中,列表是日常工作分析主要接触和使用的数据结构。元组与列表极为相似,但它们存在一个重要的区别—— 元组不可修改!字典实现了键与值的配对,可以快速实现内容的索引。集合相对少用些,它是存储数据唯一值的一个集合。四者使用的初始化符号或函数都是不同的,读者需要能够区分并熟练掌握。本章的核心在列表部分,列表的重要性不言而喻,理解列表也可以帮助读者快速理解其他几个数据结构的意义与操作方法。在接下来的章节中,本书也将更深入地介绍和运用它们。本文摘自《交互的Python:数据分析入门》Python具有强大的应用能力,以及便捷高效的数据分析和可视化扩展包系统。本书重点讲解Python数据分析的基础知识,使读者通过Python理解数据分析的逻辑,并掌握基本的Python编程知识和分析实现方法。本书系统全面、循序渐进地介绍了Python编程基础、数据导入、数据分析和可视化内容,包括条件判断与循环控制、从Excel中导入数据、使用Pandas库进行数据的转换和计算,以及使用Plotnine库绘制ggplot风格的图形等。此外,本书还涉及Markdown、基本的统计理论和IPython魔术命令等内容。

我要回帖

更多关于 假设数据段定义如下DA1 的文章

 

随机推荐