因为习惯了使用pandas的DataFrame数据结构,同时pandas作为一个方便计算和表操作的数据结构具有十分显著的优势,甚至很多时候dataFrame可以作为excel在使用,而在用python操作gis的shp文件时很不顺畅,不太符合使用习惯,故写了一个DataFrame与arcgis地理文件相互转换的函数,这个处理起来可以节约大量的思考时间。
Shp转DataFrame:
1import arcpy 2import pandas as pd 3 4def Shp2dataframe(path): 5 '''将arcpy表单变为pandas表单输出''' 6 fields=arcpy.ListFields(path) 7 table=[] 8 fieldname=[field.name for field in fields] 9 #游标集合,用for 循环一次后没办法循环第二次!一个游标实例只能循环一次 10 data=arcpy.SearchCursor(path) 11 for row in data: 12 #Shape字段中的要数是一个几何类 13 r=[] 14 for field in fields: 15 r.append(row.getValue(field.name)) 16 table.append(r) 17 return pd.DataFrame(table,columns=fieldname) 18
DataFrame转Shp:
DataFrame转Shp采用了模板形式,通过模板建立字段文件,坐标系等可以更加快速构建字段。
1#将由ReadTable读取的pandas表转换为shp格式,template为模板 2def Dataframe2ShpTemplate(df,outpath,geoType,template): 3 ''' 4 Fuction: 5 make the table of pandas's DataFrame convert to the shp of esri 6 Input: 7 df -- pandas DataFrame from the shp converted 8 outpath -- the shp output path 9 geometryType -- the type of geomentey, eg:'POINT','POLYLINE','POLYGON','MULTIPOINT' 10 temple -- the temple, at most time it is used the DataFrame's shp 11 ''' 12 out_path = outpath.replace(outpath.split('/')[-1],'') 13 out_name = outpath.split('/')[-1] 14 geometry_type = geoType 15 #template为模板,可以将里面属性全部赋予新建的要素,包括字段、坐标系 16 feature_class = arcpy.CreateFeatureclass_management( 17 out_path, out_name, geometry_type, template) 18 #'*'表示插入所有字段,但如果不用模板容易产生位置不对等 19 #cursor = arcpy.da.InsertCursor(outpath,'*') 20 for row in df.index: 21 #Shape需要改为'SHAPE@'才可以写入 22 df['SHAPE@'] = df['Shape'] 23 cursor = arcpy.da.InsertCursor(outpath,[field for field in df.columns]) 24 cursor.insertRow([df[field][row] for field in df.columns]) 25 print 'Pandas to shp finish!' 26 del cursor
实例应用:
写一个根据gps公交点Txt构建shp数据代码,代码如下:
1def readDataFile(filetype,filename,savefile): 2 #用'gbk'编码读取,读取成统一编码的unicode 3 with codecs.open(filename,encoding='gbk') as datafile: 4 5 #以列表形式读取所有文件 6 pointData = datafile.readlines() 7 #第一行删除并返回为title 8 outputFileName = 'bus'+re.findall('[0-9]*[0-9]',filename)[0]+filetype 9 #检查是否导出文件重复 10 saveEnv = arcpy.Describe(savefile) 11 for child in saveEnv.children: 12 if child.name == outputFileName: 13 outputFileName = outputFileName + '_1' 14 print 'output path is %s'%(savefile+outputFileName) 15 #设置shp文件模板 16 template = u'./dealing/temple.gdb/%s'%filetype 17 linename = filename.strip('./dealing\\').decode('gbk').encode('utf-8') 18 if filetype == 'point': 19 df = pd.DataFrame(columns=Shp2dataframe(template).columns) 20 for num in xrange(len(pointData)): 21 row = pointData[num].strip('\r\n').split(' ') 22 23 df.set_value(num,'name',row[0]) 24 df.set_value(num,'x',row[1]) 25 df.set_value(num,'y',row[2]) 26 df.set_value(num,'line',linename.strip('point.txt')) 27 28 point = arcpy.PointGeometry(arcpy.Point(row[1],row[2])) 29 df.set_value(num,'Shape',point) 30 31 elif filetype == 'line': 32 df = pd.DataFrame(columns=Shp2dataframe(template).columns) 33 pointList = [] 34 #构建线集合 35 for eachPoint in pointData: 36 coord = eachPoint.strip('\r\n').split(' ') 37 pointList.append(arcpy.Point(float(coord[0]),float(coord[1]))) 38 df.set_value(0,'name',linename.strip('line.txt')) 39 #组建线要素arcpy.Polyline(arcpy.Array(pointList)) 40 df.set_value(0,'Shape',arcpy.Polyline(arcpy.Array(pointList))) 41 42 Dataframe2ShpTemplate(df,savefile+outputFileName,'',template) 43 return df
-------sugar---------------------sugar--------------------sugar-------------------sugar----------------sugar----------
1#搜索目录下的所有带point.txt和line.txt的文件 2 3pointfiles = glob.glob('./dealing/*point.txt') 4polylinefiles = glob.glob('./dealing/*line.txt') 5 6for pf in pointfiles: 7 print pf 8 readDataFile('point',pf,u'dealing/广州市道路网.gdb/') 9 10for pl in polylinefiles: 11 print pl 12 df=readDataFile('line',pl,u'dealing/广州市道路网.gdb/') 13 14 15lineshp = arcpy.Describe(u'dealing/广州市道路网.gdb/') 16linelist = [] 17for child in lineshp.children: 18 if 'line' in child.name: 19 linelist.append(u'dealing/广州市道路网.gdb/'+child.name) 20arcpy.Merge_management(linelist,u'dealing/广州市道路网.gdb/0allLine')
Kanonpy