功能:python腳本,從csv文件的某一行開始,讀取指定列的內容,並存入一個新的csv文件
要求輸入命令行:python extract.py 1.csv 2.csv --start=2 2,3,4 表示從1.csv從第2行開始讀取2,3,4列。如果--start省略,則表示從第一行開始讀 --start=2,4表示從第2行讀到第4行
python extract.py 1.csv 2.csv --start=2 --x=2 --y=3 4,5 表示2,3列爲x,y座標,並對不在國內的座標進行座標轉換 ,寫入csv前兩列。
讀取列[2,3]與[3,2]不同,數組裏哪個列在前面就把誰寫在前列。如果有x,y參數,則x,y列放在最前面。
若用戶在命令行沒有輸入參數,或者參數不夠,則顯示腳本的用法(可用try -except實現)
方法一:用pandas包實現
將txt文件轉爲csv文件,分隔符 支持逗號、空格、|、TAB、分號,等
# -*- coding: utf-8 -*-
"""
分隔符 支持逗號、空格、|、TAB、分號,等
將txt轉爲csv文件
"""
import csv
import sys
import re
def read_file(filename):#從txt中讀取內容存入list c
f=open(filename,'r')
txt=f.read()
f.close()
str1=txt.split("\n")#首先總有換行符的,所有這個不變
temp=[]
for i in range(len(str1)):
a=re.split('[,;| \t]',str1[i])#支持分隔符,;| tab以及空格
b=[]
for j in range(len(a)):
b.append(a[j])
temp.append(b)
return temp
def write_file(outputfile,temp):
#python3以上寫入csv函數發生變化,所以加個版本判斷
if sys.version>='3':
with open(outputfile,'w',newline='') as csvfile:
writer=csv.writer(csvfile)
for row in temp:
writer.writerow(row)
else:
with open(outputfile,'wb') as csvfile:
writer=csv.writer(csvfile)
for row in temp:
writer.writerow(row)
txt=read_file("temp.txt")
write_file("ty.csv",txt)
在上述代碼讀取寫入csv代碼上增加功能,寫入前,判斷某幾列是否符合某標準,若不符合,轉換後再寫入。讀取列[2,3]與[3,2]不同,數組裏哪個列在前面就把誰寫在前列。如果有x,y參數,則x,y列放在最前面。
程序說明
==============================================================================================================================
"""
讀取csv or txt文件的指定行、列並寫入csv文件
python extract.py inputfile outputfile --start --x --y startcols
:param inputfile:可以是csv、txt文件路徑。如果是txt文件,則腳本首先將其寫入同名csv文件,支持分隔符,;| tab以及空格
:param outputfile:輸出csv文件路徑
:param --start:是一個列表,2,4表示讀inputfile的第2-4行,2表示讀第2行到最後,省略這個參數表示從頭行讀到尾
:param --x:可省略參數--y參數成對出現。--x=3 --y=4表示第3、4列分別爲經緯度座標,讀取這兩列,並對國內座標進行轉換後存入輸出csv文件
:param --y:可省略參數
:param startcols:是一個列表,2,4表示讀inputfile的第2、4列,2表示讀第二列,參數不可省
"""
# -*- coding: utf-8 -*-
"""
Created on Tue Mar 26 19:10:57 2019
"""
from __future__ import division
import pandas as pd
import numpy as np
import sys
import getopt
import math
import warnings
import csv
import re
warnings.filterwarnings("ignore") #忽略警告信息
x_pi = 3.14159265358979324 * 3000.0 / 180.0
pi = 3.1415926535897932384626 # π
percent=[0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1]
def read_file(filename):
"""
從txt文件中讀取內容存入list temp
支持分隔符,;| tab以及空格
:param filename:txt文件路徑
"""
f=open(filename,'r')
txt=f.read()
f.close()
str1=txt.split("\n")#首先總有換行符的,所有這個不變
temp=[]
for i in range(len(str1)):
a=re.split('[,;| \t]',str1[i])#支持分隔符,;| tab以及空格
b=[]
for j in range(len(a)):
b.append(a[j])
temp.append(b)
return temp
def write_file(outputfile,temp):
"""
將txt內容寫入csv文件
:param outputfile:輸出文件路徑
:param temp:從txt文件中讀取的內容list
"""
#python3以上寫入csv函數發生變化,所以加個版本判斷
if sys.version>='3':
with open(outputfile,'w',newline='') as csvfile:
writer=csv.writer(csvfile)
for row in temp:
writer.writerow(row)
else:
with open(outputfile,'wb') as csvfile:
writer=csv.writer(csvfile)
for row in temp:
writer.writerow(row)
def out_of_china(lng, lat):
"""
判斷是否在國內,不在國內不做偏移
:param lng:經度
:param lat:緯度
:return:True表示不在國內
"""
if lng < 72.004 or lng > 137.8347:
return True
if lat < 0.8293 or lat > 55.8271:
return True
def gcj02tobd09(lng, lat):
"""
火星座標系(GCJ-02)轉百度座標系(BD-09)
谷歌、高德——>百度
:param lng:火星座標經度
:param lat:火星座標緯度
:return:轉換後坐標
"""
z = math.sqrt(lng * lng + lat * lat) + 0.00002 * math.sin(lat * x_pi)
theta = math.atan2(lat, lng) + 0.000003 * math.cos(lng * x_pi)
bd_lng = z * math.cos(theta) + 0.0065
bd_lat = z * math.sin(theta) + 0.006
return [bd_lng, bd_lat]
def trans(df,a,startrow,outputfile):
"""
判斷x,y列座標是否在國內,若在國內則進行座標轉換,存入csv
:param df:讀取的csv指定行、列內容
:param a:命令行--x、--y的參數
:param startrow:命令行指定列的參數
:param outputfile:輸出文件路徑
"""
tmp=[]
for i in range(len(percent)):
tmp.append(int(len(df)*percent[i])) #爲了打印轉換進度
for i in range(len(df)):
x1=float(df[a[0]][i+startrow[0]])#獲取經度座標
y1=float(df[a[1]][i+startrow[0]])#獲取緯度座標
f=out_of_china(x1,y1) #判斷是否在國內
if f==None: #在國內則進行座標轉換
x2,y2=gcj02tobd09(x1, y1)
df[a[0]][i+startrow[0]]=x2
df[a[1]][i+startrow[0]]=y2
for index,k in enumerate(tmp): #屏幕打印座標轉換進度
if (i+1) ==k:
p="%.2f%%" % ((index+1) * 10)
print('The coordinate transformation has completed by '+p)
df.to_csv(outputfile,index=False,header=None,sep=',')
def help():#輸出腳本功能
print(unicode('===============================================================================\n \
程序說明\n \
===============================================================================\n \
讀取csv or txt文件的指定行、列並寫入csv文件\n \
命令行輸入:python extract.py inputfile outputfile --start --x --y startcols\n \
:inputfile:可以是csv、txt文件路徑。若是txt文件,則腳本首先將其寫入同名csv文件,支持分隔符,;| tab以及空格\n \
:outputfile:輸出csv文件路徑\n \
:--start:是列表,2,4表示讀inputfile的第2-4行,2表示讀第2行到最後,省略這個參數表示從頭行讀到尾\n \
:--x:可省略參數--y參數成對出現。--x=3 --y=4表示第3、4列分別爲經緯度座標,讀取這兩列,並對國內座標進行轉換後存入輸出csv文件\n \
:--y:可省略參數\n \
:startcols:是列表,2,4表示讀inputfile的第2、4列,2表示讀第二列,參數不可省\n \
===============================================================================',encoding="utf-8"))
def main(argv):
startcols=[] #存放--start參數
startrows=[] #存放列參數
xy=[] #存放--x、--y參數
try:
inputfile=sys.argv[1]#讀取的csv文件路徑
outputfile=sys.argv[2]#存儲的csv文件路徑
ass=sys.argv[3] #無用參數,只是爲了確保命令行至少有3個參數
opts,args=getopt.getopt(argv,"hu:p",["start=","x=","y="])#這裏就是爲了能夠讀取命令行的--start,--x,--y參數
except:#輸出腳本用法
help()
#如果輸入的第一個參數是txt文件,則先將其轉爲csv文件。
if inputfile[-3:]=='txt':
txt=read_file(inputfile)
name=inputfile[:-4]
inputfile=str(name+'.csv')
write_file(inputfile,txt)
#獲取命令行參數
for opt,arg in opts:
if opt in "--start":
temp1=str(arg)
arr1=[]
arr1=temp1.split(',')
for i in range(len(arr1)):
startrows.append(int(arr1[i])-1)
elif opt in "--x":
xcol=int(arg)-1
startcols.append(xcol)
elif opt in "--y":
ycol=int(arg)-1
startcols.append(ycol)
xy=startcols[:] #深複製
if len(startrows)==0:#如果不設--start參數值,默認從第一行開始
startrows=[0]
#取命令行列參數,去掉逗號分隔符
if(len(sys.argv)>3):
temp2=str(sys.argv[-1])
ar=[]
ar=temp2.split(',')
for i in range(len(ar)):
startcols.append(int(ar[i])-1)
df=pd.read_csv(inputfile,header=None,usecols=startcols)#獲取usecols指定列
#使列按數組值順序讀取
b=np.arange(len(startcols))#數組a中值得索引
for i in range(len(startcols)):
bi=df.pop(startcols[i])
df.insert(b[i],startcols[i],bi)
#獲取startrows指定行
if len(startrows)==1:
df1=df.loc[startrows[0]:]
else:
df1=df.loc[startrows[0]:startrows[1]]
#若命令行沒有--x、--y參數,則直接將截取內容存入csv文件。
if len(xy)==0:
df1.to_csv(outputfile,index=False,header=None,sep=',')
else:
trans(df1,xy,startrows,outputfile)#座標轉換+寫入csv文件
if __name__=="__main__":
main(sys.argv[3:])
方法二:
用csv包來做
enumerate() 函數用於將一個可遍歷的數據對象(如列表、元組或字符串)組合爲一個索引序列,同時列出數據和數據下標,一般用在 for 循環當中。
enumerate(sequence, [start=0])返回 enumerate(枚舉) 對象。
sequence -- 一個序列、迭代器或其他支持迭代對象。
start -- 下標起始位置。
>>>seq = ['one', 'two', 'three']
>>> for i, element in enumerate(seq):
print i, element
...
0 one
1two
2 three
下面的代碼沒有加入命令行參數,將方法一的命令行部分代碼直接套過來即可。
import csv
start=2#開始行
colls=[1,2,3]#列
inputfile='gy.csv'
outputfile='gy1.csv'
csv_file=csv.reader(open(inputfile,'r'))
temp=[]
print("==================")
for i,line in enumerate(csv_file):
if i>=start-1:
cols=[]
for j,coll in enumerate(line):
if j in colls:
cols.append(coll)
temp.append(cols)
print(temp)
print("cols")
csv_write=open(outputfile,'a',newline='')
writer=csv.writer(csv_write)
for row in temp:
writer.writerow(row)
用字典給數組賦值,修改字典鍵值
import pandas as pd
import numpy as np
def insert_sort(lists):#列表排序
lists_1=lists[:]#深複製
count=len(lists_1)
for i in range(1,count):
key=lists_1[i]
j=i-1
while j>=0:
if lists_1[j]>key:
lists_1[j+1]=lists_1[j]
lists_1[j]=key
j-=1
return lists_1
def dic(arr1,arr2):
c={}
for k,v in enumerate(arr1):#前面的是索引,後面是值
c[k]=v #給字典賦值
print(c)
lt=[]
for k,v in enumerate(arr2):#前面的是索引,後面是值
d={}
d[k]=v #給字典賦值
lt.append(d)
for k,v in c.items():
for i in range(len(lt)):
if v==lt[i].values()[0]:
lt[i][k]=lt[i].pop(lt[i].keys()[0])
return lt
arr1=[10,2,5,3]
arr2=insert_sort(arr1)
lt=dic(arr1,arr2)
print(lt)#數組字典