如何在 CSV 文件中添加新列?
Posted
技术标签:
【中文标题】如何在 CSV 文件中添加新列?【英文标题】:How to add a new column to a CSV file? 【发布时间】:2012-06-19 16:41:36 【问题描述】:我有几个类似这样的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
【问题讨论】:
Copy one column to another but with different header的可能重复 您是否可能在最后一列中只有“Berry”,因为您只是将“Berry”写入文件? (row+['Berry']) 你希望写什么? @Dhara:我想将 Berry 作为标题,将 Name 列值作为 Berry 的行值。见上文。 您还按照page中的建议使用熊猫数据框 【参考方案1】:这应该让您知道该怎么做:
>>> 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)
请注意
csv.writer
中的lineterminator
参数。默认情况下是
设置为'\r\n'
,这就是为什么你有双倍间距。
使用列表追加所有行并将它们写入
与writerows
合影。如果你的文件非常非常大,这个
可能不是一个好主意(RAM),但对于普通文件,我认为它是
更快,因为 I/O 更少。
如本文的 cmets 所示,请注意,而不是
嵌套两个with
语句,您可以在同一行中进行:
用 open('C:/test/test.csv','r') 作为 csvinput,open('C:/test/output.csv', 'w') 作为 csvoutput:
【讨论】:
感谢您的来信。我试过了,它给了我属性错误:'_csv.reader' 对象没有属性'next'。你有什么想法吗? 我看到你在 py3k 中。那么你必须使用 next(r) 而不是 r.next() @华金:天啊。谢谢你的奖金!! 注意:不用嵌套with
语句,您可以在同一行用逗号分隔它们,例如:with open(input_filename) as input_file, open(output_filename, 'w') as output_file
@Caumons 你是对的,这将是当今的发展方向。注意我的回答试图保持 OP 代码结构专注于解决他的问题。【参考方案2】:
我很惊讶没有人推荐 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 Website了解更多信息!
output.csv
的内容:
Name,Code,Berries
blackberry,1,blackberry
wineberry,2,wineberry
rasberry,1,rasberry
blueberry,1,blueberry
mulberry,2,mulberry
【讨论】:
如何在同一个csv中更新或添加新列?? input.csv?? @AnkitMaheshwari,将本例中output.csv
的名称更改为input.csv
。它会做同样的事情,但输出到input.csv
。
@AnkitMaheshwari 是的......这是预期的功能。您想按照 OP 的要求,将旧内容(带有 Name
和 Code
的内容)替换为新内容,该新内容具有与旧内容相同的两列以及带有 Berries
的新列。
请注意:Pandas 非常适合大小合适的文件。这个答案会将所有数据加载到内存中,这对于大文件可能会很麻烦。
@pedrostrusso 但是除非你加载 4-16 gb 的文件,否则你应该在 RAM 上很好。除非你用土豆。【参考方案3】:
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
【讨论】:
创建一个关于堆栈溢出的新问题。 这应该是公认的答案,因为它不会一次将所有输入行放入内存中。【参考方案4】:我用过 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
希望对您有所帮助。
【讨论】:
【参考方案5】:是的,这是一个老问题,但它可能会有所帮助
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
的使用有何评论?
只是在列中添加一些随机数据,没有规范!!!
谢谢,在列有新值(不是来自现有行)的情况下很有用,所以这是一个通用的解决方案。【参考方案6】:
我没有看到你在哪里添加新列,但试试这个:
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++
【讨论】:
【参考方案7】:此代码足以满足您的要求,并且我已经对示例代码进行了测试。
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]]
【讨论】:
【参考方案8】:如果文件很大,您可以使用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)
【讨论】:
【参考方案9】:使用不带标题名称的 python 在现有 csv 文件中追加新列
default_text = 'Some Text'
# Open the input_file in read mode and output_file in write mode
with open('problem-one-answer.csv', 'r') as read_obj, \
open('output_1.csv', 'w', newline='') as write_obj:
# Create a csv.reader object from the input file object
csv_reader = reader(read_obj)
# Create a csv.writer object from the output file object
csv_writer = csv.writer(write_obj)
# Read each row of the input csv file as list
for row in csv_reader:
# Append the default text in the row / list
row.append(default_text)
# Add the updated row / list to the output file
csv_writer.writerow(row)
谢谢
【讨论】:
【参考方案10】:对于向现有 CSV 文件(带标题)添加新列,如果要添加的列具有足够少的值,这里有一个方便的功能(有点类似于 @joaquin 的解决方案)。该函数采用
-
现有的 CSV 文件名
输出 CSV 文件名(将包含更新的内容)和
带有标题名称和列值的列表
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 文件:
输出(更新)CSV 文件:
【讨论】:
以上是关于如何在 CSV 文件中添加新列?的主要内容,如果未能解决你的问题,请参考以下文章
如何将 CSV 导出复制到添加了新列的 Redshift 表中?
如何通过读取shell脚本中的csv文件来将2列的总和添加到新列中
如何使用apache commons将新列添加到csv文件中
如何使用 apache commons 将新列添加到 csv 文件