如何向CSV文件添加新列?

86

我有几个类似这样的CSV文件:

Input
Name        Code
blackberry  1
wineberry   2
rasberry    1
blueberry   1
mulberry    2

我想向所有CSV文件添加一个新列,使其看起来像这样:

Output
Name        Code    Berry
blackberry  1   blackberry
wineberry   2   wineberry
rasberry    1   rasberry
blueberry   1   blueberry
mulberry    2   mulberry

到目前为止,我写的脚本是这样的:

import csv
with open(input.csv,'r') as csvinput:
    with open(output.csv, 'w') as csvoutput:
        writer = csv.writer(csvoutput)
        for row in csv.reader(csvinput):
            writer.writerow(row+['Berry'])

(Python 3.2)

但是在输出中,脚本跳过了每一行,新列中只有Berry:

Output
Name        Code    Berry
blackberry  1   Berry

wineberry   2   Berry

rasberry    1   Berry

blueberry   1   Berry

mulberry    2   Berry

可能是重复的问题:将一列复制到另一列,但标题不同 - Martijn Pieters
你的最后一列只有“Berry”,可能是因为你只将“Berry”写入文件中吗?(row + ['Berry']) 你原本期望写什么? - Dhara
@Dhara:我想把“Berry”作为表头,并将名称列的值作为Berry的行值。请参见上文。 - fairyberry
你也可以像这个页面建议的那样使用Pandas数据框。 - Hemanth Kumar
11个回答

109

这应该能让你了解该怎么做:

>>> v = open('C:/test/test.csv')
>>> r = csv.reader(v)
>>> row0 = r.next()
>>> row0.append('berry')
>>> print row0
['Name', 'Code', 'berry']
>>> for item in r:
...     item.append(item[0])
...     print item
...     
['blackberry', '1', 'blackberry']
['wineberry', '2', 'wineberry']
['rasberry', '1', 'rasberry']
['blueberry', '1', 'blueberry']
['mulberry', '2', 'mulberry']
>>> 

编辑,注意在 py3k 中你必须使用 next(r)

感谢接受答案。这是一个奖励(您的工作脚本):

import csv

with open('C:/test/test.csv','r') as csvinput:
    with open('C:/test/output.csv', 'w') as csvoutput:
        writer = csv.writer(csvoutput, lineterminator='\n')
        reader = csv.reader(csvinput)

        all = []
        row = next(reader)
        row.append('Berry')
        all.append(row)

        for row in reader:
            row.append(row[0])
            all.append(row)

        writer.writerows(all)

请注意:

  1. csv.writer 中的 lineterminator 参数。默认设置为 '\r\n',这就是为什么会出现双倍间距的原因。
  2. 使用列表将所有行附加并一次性使用 writerows 写入它们。如果您的文件非常大,可能不是一个好主意(占用内存),但对于普通文件来说,我认为更快,因为 I/O 操作较少。
  3. 正如此帖子中的评论所示,请注意,您可以将两个 with 语句嵌套,也可以在同一行上执行:

    with open('C:/test/test.csv','r') as csvinput, open('C:/test/output.csv', 'w') as csvoutput:


谢谢留言。我尝试了一下,但出现了属性错误:“'_csv.reader'对象没有'next'属性”。你有什么想法吗? - fairyberry
我看到你在使用py3k。那么你必须使用next(r)而不是r.next()。 - joaquin
@joaquin:天啊!谢谢你的奖金!! - fairyberry
7
注意:不需要嵌套使用 with 语句,你可以在同一行使用逗号分隔它们,例如:with open(input_filename) as input_file, open(output_filename, 'w') as output_file - Caumons
@Caumons 你说得对,这现在是应该采取的方法。请注意,我的回答试图保持OP代码结构,以便专注于解决他的问题。 - joaquin
这个答案将所有输入文件都放入内存中,以便使用writerows一次性写入所有内容,对于大小适中的文件来说还好,但对于较大的文件可能会导致内存溢出。 - pedrostrusso

82

我很惊讶没有人建议使用Pandas。虽然像Pandas这样使用一组依赖项可能看起来比这个简单的任务所需的更加笨重,但它可以产生非常短的脚本,并且Pandas是一个非常棒的库,用于进行各种CSV(以及所有数据类型)数据操作。无法反驳4行代码:

import pandas as pd
csv_input = pd.read_csv('input.csv')
csv_input['Berries'] = csv_input['Name']
csv_input.to_csv('output.csv', index=False)

查看Pandas网站获得更多信息!

output.csv的内容:

Name,Code,Berries
blackberry,1,blackberry
wineberry,2,wineberry
rasberry,1,rasberry
blueberry,1,blueberry
mulberry,2,mulberry

1
如何在同一个CSV文件中更新或添加新的列?输入文件为input.csv。 - Ankit Maheshwari
1
@AnkitMaheshwari,请将此示例中的 output.csv 文件名更改为 input.csv。这样做可以实现相同的功能,但输出到 input.csv 文件中。 - Blairg23
1
@AnkitMaheshwari 是的...那是预期的功能。您想用具有与旧内容相同的两列加上一个名为“Berries”的新列的新内容替换旧内容(即具有“Name”和“Code”的内容),正如OP所要求的那样。 - Blairg23
1
一个警告:Pandas非常适合处理中等大小的文件。这个答案将会把所有数据加载到内存中,对于大文件可能会造成麻烦。 - pedrostrusso
2
@pedrostrusso 但是除非你正在加载4-16 GB的文件,否则你的RAM应该足够了。除非你使用土豆。 - Blairg23
显示剩余8条评论

18
import csv
with open('input.csv','r') as csvinput:
    with open('output.csv', 'w') as csvoutput:
        writer = csv.writer(csvoutput)

        for row in csv.reader(csvinput):
            if row[0] == "Name":
                writer.writerow(row+["Berry"])
            else:
                writer.writerow(row+[row[0]])

也许你打算做的就是这样?

另外,csv代表逗号分隔值。所以,你需要用逗号来分隔你的值,就像这样:

Name,Code
blackberry,1
wineberry,2
rasberry,1
blueberry,1
mulberry,2

在 Stack Overflow 上创建一个新问题。 - jgritty
1
这应该是被接受的答案,因为它不会一次性将所有输入行放入内存中。 - pedrostrusso

8

这是一个老问题,但可能会对一些人有所帮助。

import csv
import uuid

# read and write csv files
with open('in_file','r') as r_csvfile:
    with open('out_file','w',newline='') as w_csvfile:

        dict_reader = csv.DictReader(r_csvfile,delimiter='|')
        #add new column with existing
        fieldnames = dict_reader.fieldnames + ['ADDITIONAL_COLUMN']
        writer_csv = csv.DictWriter(w_csvfile,fieldnames,delimiter='|')
        writer_csv.writeheader()


        for row in dict_reader:
            row['ADDITIONAL_COLUMN'] = str(uuid.uuid4().int >> 64) [0:6]
            writer_csv.writerow(row)

对于使用 uuid 有什么评论吗? - Nikos Alexandris
1
只是为了向列添加一些随机数据,没有任何规格!!! - Tpk43
谢谢,如果列具有新值(而不是现有行中的值),那么它非常有用,因此这是一个通用解决方案。 - Ahmad

7

我使用了pandas,它运行良好... 在使用它的过程中,我需要打开一个文件并添加一些随机列,然后保存到同一个文件中。

这段代码添加了多个列条目,您可以根据需要进行编辑。

import pandas as pd

csv_input = pd.read_csv('testcase.csv')         #reading my csv file
csv_input['Phone1'] = csv_input['Name']         #this would also copy the cell value 
csv_input['Phone2'] = csv_input['Name']
csv_input['Phone3'] = csv_input['Name']
csv_input['Phone4'] = csv_input['Name']
csv_input['Phone5'] = csv_input['Name']
csv_input['Country'] = csv_input['Name']
csv_input['Website'] = csv_input['Name']
csv_input.to_csv('testcase.csv', index=False)   #this writes back to your file

如果您希望不复制单元格的值,请首先在csv文件中手动创建一个空列,例如将其命名为Hours。然后,在上述代码中添加以下行即可实现此功能。
csv_input['New Value'] = csv_input['Hours']

或者说,我们可以不添加手动列,直接

csv_input['New Value'] = ''    #simple and easy

希望这可以帮助到您。


4
你可以只写:

你可以只写:

import pandas as pd
import csv
df = pd.read_csv('csv_name.csv')
df['Berry'] = df['Name']
df.to_csv("csv_name.csv",index=False)

然后你就完成了。要检查它,你可以运行:
h = pd.read_csv('csv_name.csv') 
print(h)

如果你想添加一列新的任意元素(a,b,c),你可以将代码的第四行替换为:
df['Berry'] = ['a','b','c']

3

如果要向现有的CSV文件(带标题)添加新列,如果要添加的列具有足够少的值,则可以使用方便的函数(与@joaquin的解决方案有些相似)。该函数需要以下三个参数:

  1. 现有CSV文件名
  2. 输出CSV文件名(将具有更新后的内容)
  3. 包含标题名称和列值的列表
def add_col_to_csv(csvfile,fileout,new_list):
    with open(csvfile, 'r') as read_f, \
        open(fileout, 'w', newline='') as write_f:
        csv_reader = csv.reader(read_f)
        csv_writer = csv.writer(write_f)
        i = 0
        for row in csv_reader:
            row.append(new_list[i])
            csv_writer.writerow(row)
            i += 1 

例子:

new_list1 = ['test_hdr',4,4,5,5,9,9,9]
add_col_to_csv('exists.csv','new-output.csv',new_list1)

现有的CSV文件: enter image description here

输出(更新后)的CSV文件: enter image description here


2

这段代码可以满足您的请求,我已经在示例代码上进行了测试。

import csv

with open(in_path, 'r') as f_in, open(out_path, 'w') as f_out:
    csv_reader = csv.reader(f_in, delimiter=';')
    writer = csv.writer(f_out)

    for row in csv_reader:
    writer.writerow(row + [row[0]]

2

我不知道你在哪里添加新列,但是可以试试这个:

    import csv
    i = 0
    Berry = open("newcolumn.csv","r").readlines()
    with open(input.csv,'r') as csvinput:
        with open(output.csv, 'w') as csvoutput:
            writer = csv.writer(csvoutput)
            for row in csv.reader(csvinput):
                writer.writerow(row+","+Berry[i])
                i++

2

如果文件较大,您可以使用 pandas.read_csv 并使用 chunksize 参数,该参数允许按块读取数据集:

import pandas as pd

INPUT_CSV = "input.csv"
OUTPUT_CSV = "output.csv"
CHUNKSIZE = 1_000 # Maximum number of rows in memory

header = True
mode = "w"
for chunk_df in pd.read_csv(INPUT_CSV, chunksize=CHUNKSIZE):
    chunk_df["Berry"] = chunk_df["Name"]
    # You apply any other transformation to the chunk
    # ...
    chunk_df.to_csv(OUTPUT_CSV, header=header, mode=mode)
    header = False # Do not save the header for the other chunks
    mode = "a" # 'a' stands for append mode, all the other chunks will be appended

如果您想就地更新文件,您可以使用一个临时文件,在最后将其删除。

import pandas as pd

INPUT_CSV = "input.csv"
TMP_CSV = "tmp.csv"
CHUNKSIZE = 1_000 # Maximum number of rows in memory

header = True
mode = "w"
for chunk_df in pd.read_csv(INPUT_CSV, chunksize=CHUNKSIZE):
    chunk_df["Berry"] = chunk_df["Name"]
    # You apply any other transformation to the chunk
    # ...
    chunk_df.to_csv(TMP_CSV, header=header, mode=mode)
    header = False # Do not save the header for the other chunks
    mode = "a" # 'a' stands for append mode, all the other chunks will be appended

os.replace(TMP_CSV, INPUT_CSV)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接