python:df.str.split("[")[1].split("]")[0]这个写法能否进行优化
可以使用正则表达式来替代字符串操作,更加简洁易懂。可以使用re模块中的findall方法,代码如下:
import re
result = re.findall(r'\[(.*?)\]', df)[0]
其中,r'[(.?)]' 是正则表达式,表示匹配方括号中的内容,并将其分组,(.?) 表示任意字符任意次数,直到匹配到右括号为止。findall方法返回的是一个列表,因此我们需要使用[0]来取出第一个匹配结果。
这种写法也可以避免对于可能出现的多个左右括号进行额外的处理。
python:df.str.split("[")[1].split("]")[0]这个写法行不行
这个写法可以实现将一个DataFrame中某一列的字符串按照"["和"]"进行分割并取出中间部分的功能,但是需要注意一下几点:
如果DataFrame中该列中的某些值不包含"["或"]",则会报错,因为split函数找不到相应的分隔符。
如果DataFrame中该列中的某些值包含多个"["或"]",则该写法只能取到第一个"["和最后一个"]"之间的内容,可能无法满足实际需求。
如果DataFrame中该列中的某些值为空字符串,则会报错,因为split函数无法对空字符串进行分割。
因此,在使用这个写法时需要注意上述问题,并根据实际情况进行处理。
from matplotlib.colors import LogNorm import matplotlib.pyplot as plt from mpl_toolkits.axes_grid1 import make_axes_locatable from mpl_toolkits.basemap import Basemap import cmaps import math lat_lon = [] for i in range(6000): lat_lon.append([]) for j in range(7000): lat_lon[i].append(0) df1 = open(r'D:\pollution\data\zj_nox.csv', 'r',encoding='utf-8-sig') List = [] for line in df1.readlines(): line = line.split(',') List.append(line) for i in range(0, len(List)): ilon = math.floor(round(float(List[i][2]) * 100,2)) - 7000 ilat = math.floor(round(float(List[i][3]) * 100,2)) value = str.strip(List[i][4]) lat_lon[ilat][ilon] += float(value) fig = plt.figure() ax = fig.add_subplot(111) #basemap = Basemap(llcrnrlon=119.7, llcrnrlat=29, urcrnrlon=122.7, urcrnrlat=32) basemap = Basemap(llcrnrlon=118.92, llcrnrlat=31.5, urcrnrlon=120.01, urcrnrlat=32.4) worldMap = basemap.readshapefile(r'D:\pollution\city\city', 'city') data = [[lat_lon[i][j] for j in range(len(lat_lon[0]))] for i in range(len(lat_lon))] cm = cmaps.precip3_16lev im = plt.imshow(data, interpolation='None', extent=(70, 140, 60, 0), cmap=cm, norm=LogNorm(vmin=1, vmax=10000)) divider = make_axes_locatable(ax) cax = divider.append_axes('right', size='5%', pad=0.05) plt.colorbar(im, cax=cax) plt.savefig(r'D:\pollution\pic\zj_nox.png',dpi=1000) 分析下这段代码
首先,用户导入了必要的库,比如matplotlib的LogNorm用于颜色映射的对数转换,mpl_toolkits中的Basemap用于地图绘制,还有cmaps来自定义颜色。接下来,代码初始化了一个二维列表lat_lon,大小为6000x7000,初始值为0。这可能代表经纬度网格上的污染物浓度。
然后,读取了一个CSV文件(zj_nox.csv),处理每一行数据。数据中的经度和纬度被转换为索引ilon和ilat,这里用了math.floor和round,可能是在将经纬度的小数值转换为整数索引,用于定位到lat_lon数组的相应位置。然后将第四列的值(污染物浓度)累加到对应的网格点上。
接下来是绘图部分。创建了一个figure和axes,使用Basemap设置了地图的范围,可能对应浙江地区。然后通过readshapefile加载了城市边界的数据。数据被重新组织为二维列表data,使用imshow绘制热力图,应用了LogNorm对数标准化,颜色映射使用precip3_16lev。颜色条通过make_axes_locatable添加到右侧,最后保存为高分辨率的PNG图片。
需要注意的问题可能包括:lat_lon的索引是否正确处理了经纬度的转换,Basemap的范围是否与数据范围匹配,imshow的extent参数是否正确设置,以及LogNorm的参数是否合适。此外,数据读取和处理部分可能存在效率问题,尤其是对于大型的6000x7000数组,可能会消耗大量内存。还有CSV文件的路径是否正确,以及坐标转换是否有偏移错误等潜在问题。以下是对这段Python代码的逐步分析:
库导入:
from matplotlib.colors import LogNorm # 对数颜色标准化 import matplotlib.pyplot as plt # 绘图基础库 from mpl_toolkits.axes_grid1 import make_axes_locatable # 颜色条布局工具 from mpl_toolkits.basemap import Basemap # 地理绘图库 import cmaps # 颜色映射库(可能来自WRF或自定义) import math # 数学计算
数据容器初始化:
lat_lon = [] for i in range(6000): # 创建6000行7000列的二维数组 lat_lon.append([0]*7000) # 初始化全零矩阵(更高效写法:lat_lon = [[0]*7000 for _ in range(6000)])
用于存储经纬度网格化污染数据,但存在内存浪费风险(约6000×7000×4字节≈168MB)
数据读取与处理:
with open(r'D:\pollution\data\zj_nox.csv', 'r', encoding='utf-8-sig') as df1: # 推荐使用with语句 for line in df1: parts = line.strip().split(',') lon = round(float(parts[2])*100, 2) # 经度处理(注意:可能存在精度问题) lat = round(float(parts[3])*100, 2) # 纬度处理 ilon = math.floor(lon) - 7000 # 经度索引转换(可能存在问题) ilat = math.floor(lat) # 纬度索引转换 value = float(parts[4].strip()) lat_lon[ilat][ilon] += value # 累加污染值
注意点:
- 经纬度转换逻辑可能存在问题(经度索引出现负值?)
- 未处理数组越界风险(当ilat/ilon超出6000/7000范围时)
地图绘制核心逻辑:
basemap = Basemap( llcrnrlon=118.92, llcrnrlat=31.5, # 左下角经纬度(浙江北部) urcrnrlon=120.01, urcrnrlat=32.4 # 右上角经纬度 ) basemap.readshapefile(r'D:\pollution\city\city', 'city') # 加载城市边界 data = [[lat_lon[i][j] for j in range(7000)] for i in range(6000)] # 矩阵重组(可优化) cm = cmaps.precip3_16lev # 使用降水颜色映射(可能不适用于污染数据) im = plt.imshow(data, extent=(70, 140, 60, 0), # 显示范围(似乎与Basemap范围不匹配) cmap=cm, norm=LogNorm(vmin=1, vmax=10000), # 对数标准化 interpolation='None' # 禁用插值 )
颜色条添加:
divider = make_axes_locatable(ax) cax = divider.append_axes('right', size='5%', pad=0.05) plt.colorbar(im, cax=cax) # 创建独立颜色条
输出保存:
plt.savefig(r'D:\pollution\pic\zj_nox.png', dpi=1000) # 超高分辨率输出
存在的主要问题:
坐标系统不一致:
Basemap
设置范围为$[118.92°, 120.01°] \times [31.5°, 32.4°]$imshow
的extent参数却设置为$[70, 140] \times [0, 60]$(可能显示范围错误)
索引计算问题:
- 经度索引计算:
ilon = math.floor(round(lon*100,2)) - 7000
- 当
lon=120°
时,lon*100=12000 → ilon=12000-7000=5000
- 但数组宽度为7000,索引范围应为0-6999,可能导致越界
- 经度索引计算:
内存效率问题:
- 6000×7000的二维列表初始化方式低效
- 推荐使用NumPy数组:
import numpy as np; lat_lon = np.zeros((6000,7000))
可视化效果问题:
- 使用降水颜色映射
precip3_16lev
可能不适合污染数据展示 - 高dpi(1000)输出可能导致文件过大,通常300-600dpi已足够
- 使用降水颜色映射
改进建议:
- 使用NumPy进行数组操作
- 验证坐标转换公式的正确性
- 统一Basemap范围与imshow显示范围
- 添加异常处理(文件读取、数组越界)
- 使用更适合污染数据的颜色映射(如YlOrRd)
相关推荐










