如何用Python读写CSV文件?

  • 回答 (6)
  • 关注 (0)
  • 查看 (246)

通过文本文件交换信息是在程序之间共享信息的常用方法。用于交换数据的最流行的格式之一是CSV格式。但你怎么用呢?

Pythoncsv适用于大多数情况。如果工作需要大量数据或数值分析,pandas也具有CSV解析功能,应该处理其余的工作。那么如何用Python读写CSV文件?

SundeSunde提问于
土子美互联网从业者回答于

读取CSV文件

# importing csv module import csv   # csv file name filename = "aapl.csv"  # initializing the titles and rows list fields = [] rows = []   # reading csv file with open(filename, 'r') as csvfile:     # creating a csv reader object     csvreader = csv.reader(csvfile)           # extracting field names through first row     fields = csvreader.next()       # extracting each data row one by one     for row in csvreader:         rows.append(row)       # get total number of rows     print("Total no. of rows: %d"%(csvreader.line_num))   # printing the field names print('Field names are:' + ', '.join(field for field in fields))   #  printing first 5 rows print('\nFirst 5 rows are:\n') for row in rows[:5]:     # parsing each column of a row     for col in row:         print("%10s"%col),     print('\n')

上述程序的输出如下所示:

以上示例使用CSV文件aapl.csv,可以从此处下载。 使用同一目录中的aapl.csv文件运行此程序。

让我们试着理解这段代码。

  • 使用open(filename,'r')作为csvfile: csvreader = csv.reader(csvfile) 在这里,我们首先在READ模式下打开CSV文件。文件对象名为csvfile。文件对象将转换为csv.reader对象。我们将csv.reader对象保存为csvreader
  • fields = csvreader.next() csvreader是一个可迭代的对象。因此,.next()方法返回当前行并将迭代器前进到下一行。由于我们的csv文件的第一行包含标题(或字段名称),因此我们将它们保存在名为fields的列表中。
  • 对于csvreader中的行: rows.append(行) 现在,我们使用for循环遍历剩余的行。每行都附加到名为rows的列表中。如果您尝试打印每一行,可以发现该行只是一个包含所有字段值的列表。
  • print(“行的总数:%d”%(csvreader.line_num)) csvreader.line_num只是一个计数器,它返回已迭代的行数。

写入CSV文件

# importing the csv module import csv   # field names fields = ['Name', 'Branch', 'Year', 'CGPA']   # data rows of csv file rows = [ ['Nikhil', 'COE', '2', '9.0'],          ['Sanchit', 'COE', '2', '9.1'],          ['Aditya', 'IT', '2', '9.3'],          ['Sagar', 'SE', '1', '9.5'],          ['Prateek', 'MCE', '3', '7.8'],          ['Sahil', 'EP', '2', '9.1']]   # name of csv file filename = "university_records.csv"  # writing to csv file with open(filename, 'w') as csvfile:     # creating a csv writer object     csvwriter = csv.writer(csvfile)           # writing the fields     csvwriter.writerow(fields)           # writing the data rows     csvwriter.writerows(rows)

让我们尝试分解上面的代码。

  • 字段已经定义。fields是包含所有字段名称的列表。rows是列表的列表。每行都是包含该行的字段值的列表。
  • 使用open(filename,'w')作为csvfile: csvwriter = csv.writer(csvfile) 在这里,我们首先以WRITE模式打开CSV文件。文件对象名为csvfile。文件对象将转换为csv.writer对象。我们将csv.writer对象保存为csvwriter
  • csvwriter.writerow(场) 现在我们使用writerow方法编写第一行,它只是字段名称。
  • csvwriter.writerows(行) 我们使用writerows方法一次写入多行。

将字典写入CSV文件

# importing the csv module import csv   # my data rows as dictionary objects mydict =[{'branch': 'COE', 'cgpa': '9.0', 'name': 'Nikhil', 'year': '2'},          {'branch': 'COE', 'cgpa': '9.1', 'name': 'Sanchit', 'year': '2'},          {'branch': 'IT', 'cgpa': '9.3', 'name': 'Aditya', 'year': '2'},          {'branch': 'SE', 'cgpa': '9.5', 'name': 'Sagar', 'year': '1'},          {'branch': 'MCE', 'cgpa': '7.8', 'name': 'Prateek', 'year': '3'},          {'branch': 'EP', 'cgpa': '9.1', 'name': 'Sahil', 'year': '2'}]   # field names fields = ['name', 'branch', 'year', 'cgpa']   # name of csv file filename = "university_records.csv"  # writing to csv file with open(filename, 'w') as csvfile:     # creating a csv dict writer object     writer = csv.DictWriter(csvfile, fieldnames = fields)           # writing headers (field names)     writer.writeheader()           # writing data rows     writer.writerows(mydict)

在此示例中,我们将字典mydict写入CSV文件。

  • 使用open(filename,'w')作为csvfile: writer = csv.DictWriter(csvfile,fieldnames = fields) 这里,文件对象(csvfile)被转换为DictWriter对象。 在这里,我们将fieldnames指定为参数。
  • writer.writeheader() writeheader方法使用预先指定的字段名简单地写入csv文件的第一行。
  • writer.writerows(mydict) writerows方法只是写入所有行,但在每一行中,它只写入值(而不是键)。

所以,最后,我们的CSV文件如下所示:

重点:

  • 在csv模块中,可以给出可选的dialect参数,该参数用于定义特定于特定CSV格式的一组参数。默认情况下,csv模块使用excel方言,使其与excel电子表格兼容。您可以使用register_dialect方法定义自己的方言。 这是一个例子:
     csv.register_dialect(
    'mydialect',
    delimiter = ',',
    quotechar = '"',
    doublequote = True,
    skipinitialspace = True,
    lineterminator = '\r\n',
    quoting = csv.QUOTE_MINIMAL)

现在,在定义csv.reader或csv.writer对象时,我们可以像 这样指定方言:

csvreader = csv.reader(csvfile, dialect='mydialect')
  • 现在,考虑一个CSV文件在纯文本中看起来像这样:

我们注意到分隔符不是逗号而是分号。此外,行由两个换行符而不是一行换行。在这种情况下,我们可以指定分隔符和行终止符,如下所示: csvreader = csv.reader(csvfile, delimiter = ';', lineterminator = '\n\n')

因此,这是关于如何在python程序中加载和解析CSV文件的简短而简洁的讨论。

倩倩威武只想写一辈子Java的单身狗回答于

Python有一个庞大的模块库,它包含在其发行版中。csv模块使Python程序员能够解析CSV(逗号分隔值)文件。CSV文件是一个人类可读的文本文件,其中每一行都有许多字段,以逗号或其他分隔符分隔。您可以将每一行视为一行,将每个字段视为一列。CSV格式没有标准,但它们足够相似,csv模块将能够读取绝大多数CSV文件。您还可以使用csv模块编写CSV文件。

读取CSV文件

有两种方法可以读取CSV文件。您可以使用csv模块的reader函数,也可以使用DictReader类。我们将研究这两种方法。但首先,我们需要获取一个CSV文件,以便我们解析一些内容。有许多网站以CSV格式提供有趣的信息。我们将使用世界卫生组织(WHO)网站下载有关结核病的一些信息。你可以去这里获取它:http//www.who.int/tb/country/data/download/en/。收到文件后,我们就可以开始了。准备?然后让我们看看一些代码吧!

import csv
 
#----------------------------------------------------------------------
def csv_reader(file_obj):
    """
    Read a csv file
    """
    reader = csv.reader(file_obj)
    for row in reader:
        print(" ".join(row))
 
#----------------------------------------------------------------------
if __name__ == "__main__":
    csv_path = "TB_data_dictionary_2014-02-26.csv"
    with open(csv_path, "rb") as f_obj:
        csv_reader(f_obj)

我们花一点时间来解决这个问题。首先,我们必须实际导入csv模块。然后我们创建一个非常简单的函数csv_reader,它接受一个文件对象。在函数内部,我们将文件对象传递给csv_reader函数,该函数返回一个reader对象。reader对象允许迭代,就像常规文件对象一样。这让我们迭代读取器对象中的每一行并打印出数据行,减去逗号。这是有效的,因为每一行都是一个列表,我们可以将列表中的每个元素连接在一起,形成一个长字符串。

现在让我们创建自己的CSV文件并将其提供给DictReader类。这是一个非常简单的:

first_name,last_name,address,city,state,zip_code Tyrese,Hirthe,1404 Turner Ville,Strackeport,NY,19106-8813 Jules,Dicki,2410 Estella Cape Suite 061,Lake Nickolasville,ME,00621-7435 Dedric,Medhurst,6912 Dayna Shoal,Stiedemannberg,SC,43259-2273

让我们将其保存在名为data.csv的文件中。现在我们准备使用DictReader类解析文件了。我们来试试吧:

import csv
 
#----------------------------------------------------------------------
def csv_dict_reader(file_obj):
    """
    Read a CSV file using csv.DictReader
    """
    reader = csv.DictReader(file_obj, delimiter=',')
    for line in reader:
        print(line["first_name"]),
        print(line["last_name"])
 
#----------------------------------------------------------------------
if __name__ == "__main__":
    with open("data.csv") as f_obj:
        csv_dict_reader(f_obj)

在上面的示例中,我们打开一个文件并将文件对象传递给我们之前的函数。该函数将文件对象传递给我们的DictReader类。我们告诉DictReader,分隔符是逗号。这实际上并不需要,因为代码在没有该关键字参数的情况下仍然可以工作 但是,明确这是一个好主意,所以你知道这里发生了什么。接下来,我们遍历reader对象,发现reader对象中的每一行都是一个字典。这使得打印出特定的生产线非常容易。

现在我们已经准备好学习如何将csv文件写入磁盘。

编写CSV文件

csv模块还有两种可用于编写CSV文件的方法。您可以使用writer函数或DictWriter类。我们也会看看这两个。我们将从编写器函数开始。我们来看一个简单的例子:

# Python 2.x version
import csv
 
#----------------------------------------------------------------------
def csv_writer(data, path):
    """
    Write data to a CSV file path
    """
    with open(path, "wb") as csv_file:
        writer = csv.writer(csv_file, delimiter=',')
        for line in data:
            writer.writerow(line)
 
#----------------------------------------------------------------------
if __name__ == "__main__":
    data = ["first_name,last_name,city".split(","),
            "Tyrese,Hirthe,Strackeport".split(","),
            "Jules,Dicki,Lake Nickolasville".split(","),
            "Dedric,Medhurst,Stiedemannberg".split(",")
            ]
    path = "output.csv"
    csv_writer(data, path)

在上面的代码中,我们创建了一个csv_writer函数,它接受两个参数:data和path。数据是我们在脚本底部创建的列表列表。我们使用前一个示例中的缩短版数据,并将字符串拆分为逗号。这将返回一个列表。所以我们最终得到一个如下所示的嵌套列表:

[ [ 'first_name','last_name','city' ],
  [ 'Tyrese','Hirthe','Strackeport' ],
  [ 'Jules','Dicki','Lake Nickolasville' ],
  [ 'Dedric',' Medhurst','Stiedemannberg' ] ]

csv_writer函数打开,我们传递并创建一个CSV作家对象的路径。然后我们遍历嵌套列表结构并将每一行写入磁盘。请注意,我们在创建writer对象时指定了分隔符应该是什么。如果您希望分隔符是逗号之外的其他内容,则可以在此处设置它。

现在,如果您想在Python 3中编写csv文件,语法略有不同。以下是您必须重写函数的方法:

# Python 3.x version
import csv
 
def csv_writer(data, path):
    """
    Write data to a CSV file path
    """
    with open(path, "w", newline='') as csv_file:
        writer = csv.writer(csv_file, delimiter=',')
        for line in data:
            writer.writerow(line)

您将注意到需要将写入模式更改为“w”并添加换行参数。

现在我们已经准备好学习如何使用DictWriter类编写CSV文件了!我们将使用之前版本的数据并将其转换为我们可以提供给饥饿的DictWriter的字典列表。让我们来看看:

# Python 2.x version
import csv
 
#----------------------------------------------------------------------
def csv_dict_writer(path, fieldnames, data):
    """
    Writes a CSV file using DictWriter
    """
    with open(path, "wb") as out_file:
        writer = csv.DictWriter(out_file, delimiter=',', fieldnames=fieldnames)
        writer.writeheader()
        for row in data:
            writer.writerow(row)
 
#----------------------------------------------------------------------
if __name__ == "__main__":
    data = ["first_name,last_name,city".split(","),
            "Tyrese,Hirthe,Strackeport".split(","),
            "Jules,Dicki,Lake Nickolasville".split(","),
            "Dedric,Medhurst,Stiedemannberg".split(",")
            ]
    my_list = []
    fieldnames = data[0]
    for values in data[1:]:
        inner_dict = dict(zip(fieldnames, values))
        my_list.append(inner_dict)
 
    path = "dict_output.csv"
    csv_dict_writer(path, fieldnames, my_list)

注意:要将此代码转换为Python 3语法,您需要像以前一样更改with语句:使用open(path,“w”,newline =“)作为out_file:

我们将首先从第二部分开始。如您所见,我们从之前使用的嵌套列表结构开始。接下来,我们创建并清空列表和包含字段名称的列表,该列表恰好是嵌套列表中的第一个列表。记住,列表是从零开始的,因此列表中的第一个元素从零开始!接下来,我们循环遍历嵌套列表构造,从第二个元素开始:

for values in data[1:]:
    inner_dict = dict(zip(fieldnames, values))
    my_list.append(inner_dict)

for循环中,我们使用Python内置来创建字典。** zip **方法将采用两个迭代器(在本例中为列表)并将它们转换为元组列表。这是一个例子:

zip(fieldnames, values)
[('first_name', 'Dedric'), ('last_name', 'Medhurst'), ('city', 'Stiedemannberg')]

现在当你在** dict **中调用它时,它会将元组列表转换为字典。最后,我们将字典附加到列表中。当** for **结束时,你最终会得到一个如下所示的数据结构:

[{'city': 'Strackeport', 'first_name': 'Tyrese', 'last_name': 'Hirthe'},
{'city': 'Lake Nickolasville', 'first_name': 'Jules', 'last_name': 'Dicki'},
{'city': 'Stiedemannberg', 'first_name': 'Dedric', 'last_name': 'Medhurst'}]

在第二个会话结束时,我们调用我们的csv_dict_writer函数并传入所有必需的参数。在函数内部,我们创建一个DictWriter实例并传递一个文件对象,一个分隔符值和我们的字段名称列表。接下来,我们将字段名称写入磁盘并一次一行地循环数据,将数据写入磁盘。DictWriter类也支持writerows方法,我们可以使用它来代替循环。该csv.writer功能也支持此功能。

红雷如人生如梦回答于

首先,您需要导入csv

例如:

import csv

with open('eggs.csv', 'wb') as csvfile:
    spamwriter = csv.writer(csvfile, delimiter=' ',
                        quotechar='|', quoting=csv.QUOTE_MINIMAL)
    spamwriter.writerow(['Spam'] * 5 + ['Baked Beans'])
    spamwriter.writerow(['Spam', 'Lovely Spam', 'Wonderful Spam'])
akjok54stay hungry stay foolish回答于
# -*- coding: utf-8 -*-

import csv
import sys

# Define data
data = [(1, "A towel,", 1.0),
        (42, " it says, ", 2.0),
        (1337, "is about the most ", -1),
        (0, "massively useful thing ", 123),
        (-2, "an interstellar hitchhiker can have.", 3)]

# Write CSV file
kwargs = {'newline': ''}
mode = 'w'
if sys.version_info < (3, 0):
    kwargs.pop('newline', None)
    mode = 'wb'

with open('test.csv', mode, **kwargs) as fp:
    writer = csv.writer(fp, delimiter=',')
    # writer.writerow(["your", "header", "foo"])  # write header
    writer.writerows(data)

# Read CSV file
kwargs = {'newline': ''}
mode = 'r'
if sys.version_info < (3, 0):
    kwargs.pop('newline', None)
    mode = 'rb'
with open('test.csv', mode, **kwargs) as fp:
    reader = csv.reader(fp, delimiter=',', quotechar='"')
    # next(reader, None)  # skip the headers
    data_read = [row for row in reader]

print(data_read)

之后,内容data_read

[['1', 'A towel,', '1.0'],
 ['42', ' it says, ', '2.0'],
 ['1337', 'is about the most ', '-1'],
 ['0', 'massively useful thing ', '123'],
 ['-2', 'an interstellar hitchhiker can have.', '3']]

Unicode和Python 2.X

如果要编写Unicode,则必须安装unicodecsv。千万不能用打开文件codecs.open,而只是用open。用它写

import unicodecsv as csv
# Write CSV file
with open('test.csv', 'w', newline='') as fp:
    writer = csv.writer(fp, encoding='utf-8')
    # writer.writerow(["your", "header", "foo"])  # write header
    writer.writerows(data)

创建了CSV文件

1,"A towel,",1.0
42," it says, ",2.0
1337,is about the most ,-1
0,massively useful thing ,123
-2,an interstellar hitchhiker can have.,3

leosslyc回答于

使用Python读取和写入逗号分隔的文件。

CSV(逗号分隔值)文件通常用于存储和检索许多不同类型的数据。CSV格式是最灵活,最简单的格式之一。

例如,CSV文件可用于存储X,Y,Z坐标值中的点位置:

0.58,-3.7,0
0.58,-3.1,0
-0.23,0.91,0
-5,8.2,0
-3,9.2,0
2.1,8.8,0
2.5,5.5,0
6.2,1.6,0
6,1,0

或者CSV可能包含建筑数据,例如数据库类型格式的房间和使用信息。请注意,此CSV在第一行有标题标题:

RoomID,Floor,Use,Square Footage,Capacity,Price
100,1,Retail,6598,55,6500
101,1,Retail,1900,25,3000
102,1,Retail,1850,25,3000
103,1,Restroom,250,0,0
104,1,Maintenance,150,0,0
200,2,Studio,875,2,850
201,2,Studio,734,2,850
202,2,Studio,624,2,850
203,2,Studio,624,2,850

Python中的csv模块可用于快速将CSV文件解析为不同的数据结构。在此示例中,我们将读取点坐标文件到列表中,其中X,Y和Z坐标可以由列表中的索引位置引用。建筑数据将被读入字典对象,以便标题标题可以将各种值引用为命名的信息片段。

读入列表

以下是将CSV文件读入列表的示例脚本。每行将成为自己的列表,然后可以通过索引位置引用:

import csv
import rhinoscriptsyntax as rs

def CSVlist():
    #prompt the user for a file to import
    filter = "CSV file (*.csv)|*.csv|*.txt|All Files (*.*)|*.*||"
    filename = rs.OpenFileName("Open Point File", filter)
    if not filename: return

    with open(filename) as csvfile:
        reader = csv.reader(csvfile)
        for row in reader:
            x = float(row[0])
            y = float(row[1])
            z = float(row[2])
            print x, y, z
            rs.AddPoint(x,y,z)

##########################################################################
# Check to see if this file is being executed as the "main" python
# script instead of being used as a module by some other python script
# This allows us to use the module which ever way we want.
if( __name__ == "__main__" ):
    CSVlist()

像往常一样,脚本以导入开头。这次使用csv模块。

import csv

第2行到第8行是Rhino.Python的标准行。如何阅读和编写简单的文件指南。

在第10行,文件被打开以供阅读。

with open(filename) as csvfile:

然后脚本中的键函数.reader将每一行读入变量中的值列表reader

        reader = csv.reader(csvfile)

csv.reader方法将每行解析为列表。然后将每行的每个值放入一个列表中:

['0.58', '-3.7', '0']
['0.58', '-3.1', '0']
['-0.23', '0.91', '0']
['-5', '8.2', '0']
['-3', '9.2', '0']
['2.1', '8.8', '0']
['2.5', '5.5', '0']
['6.2', '1.6', '0']
['6', '1', '0']

操作列表的每一行变得容易:

        for row in reader:
            x = float(row[0])
            y = float(row[1])
            z = float(row[2])
            print x, y, z
            rs.AddPoint(x,y,z)

在这种情况下,值被分成3个变量(x,y,z),然后打印到控制台,另外用于向Rhino添加新的点对象。

将CSV文件读入列表非常适合于每行中具有相同数值的数据,并且值的位置相同。 但是,有时更容易将csv值读入字典中,其中值具有名称。

读入字典

下一个示例脚本与上面非常类似。

import csv
import rhinoscriptsyntax as rs


def CSVbuilding():
    #prompt the user for a file to import
    filter = "CSV file (*.csv)|*.csv|*.txt|All Files (*.*)|*.*||"
    filename = rs.OpenFileName("Open Point File", filter)
    if not filename: return

    with open(filename) as csvfile:
        reader = csv.DictReader(csvfile)
        for row in reader:
            print(row['Use'], row['Square Footage'])
#            print(row)

##########################################################################
# Check to see if this file is being executed as the "main" python
# script instead of being used as a module by some other python script
# This allows us to use the module which ever way we want.
if( __name__ == "__main__" ):
    CSVbuilding()

此脚本使用第12行的csv模块中的字典阅读器:

        reader = csv.DictReader(csvfile)

字典对象包含键:值,其中值的名称(键)可用于通过数据搜索对。完整的字典对象如下所示:

{'Floor':'1', 'Use':'Retail', 'Square Footage':'6598', 'Price':'6500', 'RoomID':'100', 'Capacity':'55'}
{'Floor':'1', 'Use':'Retail', 'Square Footage':'1900', 'Price':'3000', 'RoomID':'101', 'Capacity':'25'}
{'Floor':'1', 'Use':'Retail', 'Square Footage':'1850', 'Price':'3000', 'RoomID':'102', 'Capacity':'25'}
{'Floor':'1', 'Use':'Restroom', 'Square Footage':'250', 'Price':'0', 'RoomID':'103', 'Capacity':'0'}
{'Floor':'1', 'Use':'Maintenance', 'Square Footage':'150', 'Price':'0', 'RoomID':'104', 'Capacity':'0'}
{'Floor':'2', 'Use':'Studio', 'Square Footage':'875', 'Price':'850', 'RoomID':'200', 'Capacity':'2'}
{'Floor':'2', 'Use':'Studio', 'Square Footage':'734', 'Price':'850', 'RoomID':'201', 'Capacity':'2'}
{'Floor':'2', 'Use':'Studio', 'Square Footage':'624', 'Price':'850', 'RoomID':'202', 'Capacity':'2'}
{'Floor':'2', 'Use':'Studio', 'Square Footage':'624', 'Price':'850', 'RoomID':'203', 'Capacity':'2'}
{'Floor':'2', 'Use':'Double', 'Square Footage':'850', 'Price':'1245', 'RoomID':'204', 'Capacity':'4'}
{'Floor':'2', 'Use':'Double', 'Square Footage':'850', 'Price':'1245', 'RoomID':'205', 'Capacity':'4'}
{'Floor':'2', 'Use':'Double', 'Square Footage':'850', 'Price':'1245', 'RoomID':'206', 'Capacity':'4'}
{'Floor':'2', 'Use':'Double', 'Square Footage':'850', 'Price':'1245', 'RoomID':'207', 'Capacity':'4'}
{'Floor':'2', 'Use':'Common', 'Square Footage':'731', 'Price':'0', 'RoomID':'208', 'Capacity':'0'}
{'Floor':'2', 'Use':'Quad', 'Square Footage':'1100', 'Price':'1650', 'RoomID':'209', 'Capacity':'8'}
{'Floor':'2', 'Use':'Quad', 'Square Footage':'1005', 'Price':'1650', 'RoomID':'210', 'Capacity':'8'}
{'Floor':'2', 'Use':'Quad', 'Square Footage':'1205', 'Price':'1650', 'RoomID':'211', 'Capacity':'8'}

现在由于每个值都以一个键开头,因此可以通过搜索键名来找到值。例如,在这种情况下,脚本打印每行Use以及Square Footage

        for row in reader:
            print(row['Use'], row['Square Footage'])

有许多方法可以使用字典数据。只是为了添加到这个例子中,这里是代码来添加Retail建筑物空间中的所有平方英尺:

    with open(filename) as csvfile:
        reader = csv.DictReader(csvfile)
        total = 0
        for row in reader:
            if row['Use'] == 'Retail':
                total += float(row['Square Footage'])
        print "Retail space = {} sq. ft".format(total)

这里的For语句循环遍历包含“零售”的每一行,然后将每个行的平方英尺添加到total变量中。最后,它在控制台中打印总数。

通过使用该csv.DictReader()方法,简单的CSV数据可以变成更复杂的信息字典。这是一个非常强大的工具。

编写CSV文件

编写文件类似于阅读,但完成任务的顺序是不同的。这次我们将查看ExportPoints.py示例文件。

import csv
import rhinoscriptsyntax as rs

def CSVwrite():
    #Get the filename to create
    filter = "CSV File (*.csv)|*.csv|*.txt|All Files (*.*)|*.*||"
    filename = rs.SaveFileName("Save point coordinates as", filter)
    if( filename==None ): return

    points = rs.GetPoints(draw_lines=False, message1="Pick points to save to CSV:")
    if( points==None): return


    with open(filename, "wb") as csvfile:
        csvwriter = csv.writer(csvfile,  delimiter=',')
        for point in points:
            csvwriter.writerow([point[0], point[1], point[2]])
        print "Points written sucessfully to file"

##########################################################################
# Check to see if this file is being executed as the "main" python
# script instead of being used as a module by some other python script
# This allows us to use the module which ever way we want.
if( __name__ == "__main__" ):
    CSVwrite()

第1行到第8行是Rhino.Python的标准行。如何读取和编写简单的文件指南。

与前一个示例相比,有几点需要注意。我们需要一些点来导出,所以我们将让用户选择一些点对象。然后检查是否选择了一些点:

    points = rs.GetPoints(draw_lines=False, message1="Pick points to save to CSV:")
    if( points==None): return

第14行到第18行打开文件进行写入。然后,该脚本使用该.writerow方法遍历列表中的所有点。写行方法采用值列表,并将列表添加为CSV文件中的一行。

    with open(filename, "wb") as csvfile:
        csvwriter = csv.writer(csvfile,  delimiter=',')
        for point in points:
            csvwriter.writerow([point[0], point[1], point[2]])
        print "Points written sucessfully to file"

.writerow方法非常适合以最简单的CSV格式写出各种值。

写出一个字典对象

与read方法一样,还有一种方法可以将字典对象写入CSV文件。这是将任何字典数据格式化为电子表格或表格格式的好方法。

import csv
import rhinoscriptsyntax as rs

def CSVwrite():
    #Get the filename to create
    filter = "CSV File (*.csv)|*.csv|*.txt|All Files (*.*)|*.*||"
    filename = rs.SaveFileName("Save point coordinates as", filter)
    if( filename==None ): return

    dict = [
    {'Floor':'1', 'Use':'Retail', 'Square Footage':'6598', 'RoomID':'100'},
    {'Floor':'1', 'Use':'Retail', 'Square Footage':'1900', 'RoomID':'101'},
    {'Floor':'1', 'Use':'Retail', 'Square Footage':'1850', 'RoomID':'102'},
    {'Floor':'1', 'Use':'Restroom', 'Square Footage':'250', 'RoomID':'103'},
    {'Floor':'1', 'Use':'Maintenance', 'Square Footage':'150', 'RoomID':'104'}
    ]


    with open(filename, "wb") as csvfile:
        fieldnames = ('Floor', 'Use', 'Square Footage', 'Price', 'RoomID', 'Capacity')
        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)

        writer.writeheader()
        for row in dict:
            writer.writerow(row)

##########################################################################
# Check to see if this file is being executed as the "main" python
# script instead of being used as a module by some other python script
# This allows us to use the module which ever way we want.
if( __name__ == "__main__" ):
    CSVwrite()

在第10-16行,我们设置了一个词典列表。标题名称与字典中的键名称相对应。的.DictWriter类可以使用在锁中的相同的值来写CSV写在CSV的报头。

生成的CSV文件格式如下:

Floor,Use,Square Footage,RoomID
1,Retail,6598,100
1,Retail,1900,101
1,Retail,1850,102
1,Restroom,250,103
1,Maintenance,150,104
a563831029跑龙套 走马灯回答于

什么是CSV文件?

CSV文件(逗号分隔值文件)是一种纯文本文件,它使用特定的结构来排列表格数据。因为它是纯文本文件,所以它只能包含实际的文本数据 - 换句话说,可以包含可打印的ASCIIUnicode字符。

CSV文件的结构由其名称给出。通常,CSV文件使用逗号分隔每个特定数据值。这是结构的样子:

column 1 name,column 2 name, column 3 name
first row data 1,first row data 2,first row data 3
second row data 1,second row data 2,second row data 3
...

注意每个数据如何用逗号分隔。通常,第一行标识每条数据 - 换句话说,标识数据列的名称。之后的每个后续行都是实际数据,并且仅受文件大小限制的限制。

通常,分隔符称为分隔符,逗号不是唯一使用的分隔符。其他流行的分隔符包括tab(\t),冒号(:)和分号(;)字符。正确解析CSV文件需要我们知道正在使用哪个分隔符。

CSV文件来自哪里?

CSV文件通常由处理大量数据的程序创建。它们是从电子表格和数据库导出数据以及在其他程序中导入或使用数据的便捷方式。例如,您可以将数据挖掘程序的结果导出到CSV文件,然后将其导入电子表格以分析数据,生成演示文稿的图形或准备报告以供发布。

CSV文件非常易于以编程方式工作。任何支持文本文件输入和字符串操作的语言(如Python)都可以直接使用CSV文件。

使用Python的内置CSV库解析CSV文件

csv提供读取和写入CSV文件的功能。设计为使用Excel生成的CSV文件开箱即用,它可以轻松适应各种CSV格式。该csv库包含用于从CSV文件读取,写入和处理数据的对象和其他代码。

用CSV读取CSV文件 csv

使用该reader对象从CSV文件中读取。CSV文件作为文本文件打开,具有Python的内置open()函数,该函数返回文件对象。然后将其传递给reader,这将进行繁重的工作。

这是employee_birthday.txt文件:

name,department,birthday month
John Smith,Accounting,November
Erica Meyers,IT,March

这是读它的代码:

import csv

with open('employee_birthday.txt') as csv_file:
    csv_reader = csv.reader(csv_file, delimiter=',')
    line_count = 0
    for row in csv_reader:
        if line_count == 0:
            print(f'Column names are {", ".join(row)}')
            line_count += 1
        else:
            print(f'\t{row[0]} works in the {row[1]} department, and was born in {row[2]}.')
            line_count += 1
    print(f'Processed {line_count} lines.')

这导致以下输出:

Column names are name, department, birthday month
    John Smith works in the Accounting department, and was born in November.
    Erica Meyers works in the IT department, and was born in March.
Processed 3 lines.

返回的每一行reader都是一个String元素列表,其中包含通过删除分隔符找到的数据。返回的第一行包含列名称,以特殊方式处理。

用CSV将CSV文件读入字典 csv

String您可以将CSV数据直接读入字典(技术上,也可以是有序字典),而不是处理单个元素列表。

我们的输入文件再次employee_birthday.txt如下:

name,department,birthday month
John Smith,Accounting,November
Erica Meyers,IT,March

这是这次以字典形式阅读的代码:

import csv

with open('employee_birthday.txt', mode='r') as csv_file:
    csv_reader = csv.DictReader(csv_file)
    line_count = 0
    for row in csv_reader:
        if line_count == 0:
            print(f'Column names are {", ".join(row)}')
            line_count += 1
        print(f'\t{row["name"]} works in the {row["department"]} department, and was born in {row["birthday month"]}.')
        line_count += 1
    print(f'Processed {line_count} lines.')

这导致与以前相同的输出:

Column names are name, department, birthday month
    John Smith works in the Accounting department, and was born in November.
    Erica Meyers works in the IT department, and was born in March.
Processed 3 lines.

字典键来自哪里?假定CSV文件的第一行包含用于构建字典的键。如果您的CSV文件中没有这些,则应通过将fieldnames可选参数设置为包含它们的列表来指定自己的密钥。

可选的Python CSV reader参数

reader对象可以通过指定其他参数来处理不同样式的CSV文件,其中一些参数如下所示:

  • delimiter指定用于分隔每个字段的字符。默认值为逗号(',')。
  • quotechar指定用于包围包含分隔符字符的字段的字符。默认值是双引号(' " ')。
  • escapechar如果未使用引号,则指定用于转义分隔符的字符。默认值为无转义字符。

这些参数值得更多解释。假设您正在使用以下employee_addresses.txt文件:

name,address,date joined
john smith,1132 Anywhere Lane Hoboken NJ, 07030,Jan 4
erica meyers,1234 Smith Lane Hoboken NJ, 07030,March 2

此CSV文件包含三个字段:nameaddress,和date joined,这是由逗号分隔。问题是该address字段的数据还包含一个逗号来表示邮政编码。

处理这种情况有三种不同的方法:

  • 使用不同的分隔符 这样,逗号可以安全地用在数据本身中。您可以使用delimiter可选参数指定新分隔符。
  • 用引号括起数据 在引用的字符串中忽略所选分隔符的特殊性质。因此,您可以使用quotechar可选参数指定用于引用的字符。只要该字符也没有出现在数据中,你就可以了。
  • 转义数据中的分隔符字符 Escape字符的工作方式与格式字符串中的相同,从而使转义字符的解释无效(在本例中为分隔符)。如果使用转义字符,则必须使用escapechar可选参数指定它。

用CSV编写CSV文件 csv

您还可以使用writer对象和.write_row()方法写入CSV文件:

import csv

with open('employee_file.csv', mode='w') as employee_file:
    employee_writer = csv.writer(employee_file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)

    employee_writer.writerow(['John Smith', 'Accounting', 'November'])
    employee_writer.writerow(['Erica Meyers', 'IT', 'March'])

quotechar可选参数告诉writer写作时要使用引号领域的字符。但是,是否使用引用,由quoting可选参数决定:

  • 如果quoting设置为csv.QUOTE_MINIMAL,则.writerow()仅当它们包含delimiter或时引用字段quotechar。这是默认情况。
  • 如果quoting设置为csv.QUOTE_ALL.writerow()则将引用所有字段。
  • 如果quoting设置为csv.QUOTE_NONNUMERIC.writerow()则将引用包含文本数据的所有字段,并将所有数字字段转换为float数据类型。
  • 如果quoting设置为csv.QUOTE_NONE.writerow()则将转义分隔符而不是引用它们。在这种情况下,您还必须为escapechar可选参数提供值。

以纯文本格式读回文件表明该文件创建如下:

John Smith,Accounting,November
Erica Meyers,IT,March

用字典编写CSV文件 csv

由于您可以将我们的数据读入字典,因此您应该能够从字典中将其写出来是公平的:

import csv

with open('employee_file2.csv', mode='w') as csv_file:
    fieldnames = ['emp_name', 'dept', 'birth_month']
    writer = csv.DictWriter(csv_file, fieldnames=fieldnames)

    writer.writeheader()
    writer.writerow({'emp_name': 'John Smith', 'dept': 'Accounting', 'birth_month': 'November'})
    writer.writerow({'emp_name': 'Erica Meyers', 'dept': 'IT', 'birth_month': 'March'})

与此不同DictReaderfieldnames编写字典时需要参数。这是有道理的,当你想到它时:如果没有列表fieldnamesDictWriter就无法知道用哪些键从你的词典中检索值。它还使用键fieldnames将第一行写为列名。

上面的代码生成以下输出文件:

emp_name,dept,birth_month
John Smith,Accounting,November
Erica Meyers,IT,March

使用pandas库解析CSV文件

当然,Python CSV库并不是城里唯一的游戏。也可以读取CSV文件pandas。如果您要分析大量数据,强烈建议使用。

pandas是一个开源Python库,提供高性能数据分析工具和易于使用的数据结构。pandas适用于所有Python安装,但它是Anaconda发行版的关键部分,在Jupyter笔记本中非常有效,可以共享数据,代码,分析结果,可视化和叙述文本。

安装pandas及其依赖项Anaconda很容易完成:

$ conda install pandas

与使用pip/pipenv用于其他Python安装一样:

$ pip install pandas

我们不会深入研究如何pandas工作或如何使用它的具体细节。有关使用pandas读取和分析大型数据集的深入处理,请查看Shantnu Tiwari关于使用pandas中的大型Excel文件精湛文章。

用CSV读取CSV文件 pandas

为了展示pandasCSV功能的一些强大功能,我创建了一个稍微复杂的文件来读取,称为hrdata.csv。它包含公司员工的数据:

Name,Hire Date,Salary,Sick Days remaining
Graham Chapman,03/15/14,50000.00,10
John Cleese,06/01/15,65000.00,8
Eric Idle,05/12/14,45000.00,10
Terry Jones,11/01/13,70000.00,3
Terry Gilliam,08/12/14,48000.00,7
Michael Palin,05/23/13,66000.00,8

将CSV读入a pandas DataFrame是快速而直接的:

import pandas
df = pandas.read_csv('hrdata.csv')
print(df)

就是这样:三行代码,其中只有一行正在进行实际工作。pandas.read_csv()打开,分析和读取提供的CSV文件,并将数据存储在DataFrame中DataFrame在以下输出中打印结果:

             Name Hire Date   Salary  Sick Days remaining
0  Graham Chapman  03/15/14  50000.0                   10
1     John Cleese  06/01/15  65000.0                    8
2       Eric Idle  05/12/14  45000.0                   10
3     Terry Jones  11/01/13  70000.0                    3
4   Terry Gilliam  08/12/14  48000.0                    7
5   Michael Palin  05/23/13  66000.0                    8

以下是值得注意的几点:

  • 首先,pandas认识到CSV的第一行包含列名,并自动使用它们。我称之为善良。
  • 但是,pandas也使用了从零开始的整数索引DataFrame。那是因为我们没有告诉它我们的索引应该是什么。
  • 此外,如果查看列的数据类型,您将看到pandas已将列SalarySick Days remaining列正确转换为数字,但Hire Date列仍然是String。这在交互模式下很容易确认: >>>>>> print (type (df [ 'Hire Date' ] [ 0 ])) <class'str'>

让我们一次解决这些问题。要使用其他列作为DataFrame索引,请添加index_col可选参数:

import pandas
df = pandas.read_csv('hrdata.csv')
print(df)

现在该Name字段是我们的DataFrame索引:

               Hire Date   Salary  Sick Days remaining
Name                                                  
Graham Chapman  03/15/14  50000.0                   10
John Cleese     06/01/15  65000.0                    8
Eric Idle       05/12/14  45000.0                   10
Terry Jones     11/01/13  70000.0                    3
Terry Gilliam   08/12/14  48000.0                    7
Michael Palin   05/23/13  66000.0                    8

接下来,让我们修复Hire Date字段的数据类型。您可以强制pandas使用parse_dates可选参数将数据读取为日期,可选参数定义为要作为日期处理的列名列表:

import pandas
df = pandas.read_csv('hrdata.csv', index_col='Name', parse_dates=['Hire Date'])
print(df)

注意输出的差异:

                Hire Date   Salary  Sick Days remaining
Name                                                   
Graham Chapman 2014-03-15  50000.0                   10
John Cleese    2015-06-01  65000.0                    8
Eric Idle      2014-05-12  45000.0                   10
Terry Jones    2013-11-01  70000.0                    3
Terry Gilliam  2014-08-12  48000.0                    7
Michael Palin  2013-05-23  66000.0                    8

现在日期格式正确,可以在交互模式下轻松确认:

>>>

>>> print (type (df [ 'Hire Date' ] [ 0 ]))
<class'pandas._libs.tslibs.timestamps.Timestamp'>

如果CSV文件的第一行中没有列名,则可以使用namesoptional参数提供列名列表。如果要覆盖第一行中提供的列名,也可以使用此选项。在这种情况下,您还必须pandas.read_csv()使用header=0可选参数来忽略现有列名:

import pandas
df = pandas.read_csv('hrdata.csv', 
            index_col='Employee', 
            parse_dates=['Hired'], 
            header=0, 
            names=['Employee', 'Hired','Salary', 'Sick Days'])
print(df)

请注意,由于列名称已更改,因此还必须更改在index_colparse_dates可选参数中指定的列。现在这会产生以下输出:

                    Hired   Salary  Sick Days
Employee                                     
Graham Chapman 2014-03-15  50000.0         10
John Cleese    2015-06-01  65000.0          8
Eric Idle      2014-05-12  45000.0         10
Terry Jones    2013-11-01  70000.0          3
Terry Gilliam  2014-08-12  48000.0          7
Michael Palin  2013-05-23  66000.0          8

用CSV编写CSV文件 pandas

当然,如果你无法pandas再次获取数据,那对你的好处并不大。写入DataFrameCSV文件就像读取文件一样简单。让我们将带有新列名称的数据写入新的CSV文件:

import pandas
df = pandas.read_csv('hrdata.csv', 
            index_col='Employee', 
            parse_dates=['Hired'],
            header=0, 
            names=['Employee', 'Hired', 'Salary', 'Sick Days'])
df.to_csv('hrdata_modified.csv')

此代码与上面的阅读代码之间的唯一区别是,print(df)调用被替换为df.to_csv(),提供文件名。新的CSV文件如下所示:

Employee,Hired,Salary,Sick Days
Graham Chapman,2014-03-15,50000.0,10
John Cleese,2015-06-01,65000.0,8
Eric Idle,2014-05-12,45000.0,10
Terry Jones,2013-11-01,70000.0,3
Terry Gilliam,2014-08-12,48000.0,7
Michael Palin,2013-05-23,66000.0,8

扫码关注云+社区