python 讀取、寫入csv文件,txt轉csv

功能: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)#數組字典

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章