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)#数组字典

 

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