如何更改 .csv 文件中一行的最后一个值
Posted
技术标签:
【中文标题】如何更改 .csv 文件中一行的最后一个值【英文标题】:How to change the last value of a row in .csv file 【发布时间】:2019-11-21 04:02:20 【问题描述】:我正在使用 CLI 创建一个待办事项列表,我想将一行的最后一个值,即状态从“未完成”更改为“完成”
我知道我们不能像那样编辑 csv 文件,所以我们要做的是读取它更改值然后覆盖现有文件。 这是 csv 文件:https://drive.google.com/open?id=1fqc79mtVmZGZ_pb_2zrzDGVDmyMFWi6C 我试过这个:
import csv
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-o', '--option', metavar='', help='-o <option> write either you want to add or view')
parser.add_argument('-l', '--select', metavar='', help='-l <used to select the task for modification')
args = parser.parse_args()
def modify():
select = args.select
with open('csv.csv', 'r+', newline='') as file:
lines = list(file)
lines[int(select)][7] = 1
with open('csv.csv', 'w+', newline='') as ifile:
writer = csv.writer(ifile)
writer.writerows(lines)
当我们运行这个时我想要那个:
python todoarg.py -o modify -l 2
它将第二行的状态从“未完成”更改为“完成”
【问题讨论】:
你目前得到了什么? 您是否收到错误消息?始终将完整的错误消息(从单词“Traceback”开始)放在问题中(作为文本,而不是屏幕截图)。还有其他有用的信息。 这就是你的全部代码吗?你为什么不运行函数modify()
?
【参考方案1】:
我也找到了一种不用 pandas 的方法:
def modify():
with open("csv.csv", 'r+') as f:
lines = f.readlines()
f.seek(0)
task = args.select
for line in lines:
if not task in line.split(',')[0]:
f.write(line)
for line in lines:
if task in line.split(',')[0]:
#what we do here is print existing values using their index
#with split function and adding 'Complete' instead of
#6th index which was 'Incomplete'
f.write('\n' + line.split(',')[0] + ',' + line.split(',')[1] + ',' + line.split(',')[2] + ','
+ line.split(',')[3] + ',' + line.split(',')[4] + ','
+ line.split(',')[5] + ',' + 'Complete')
f.truncate()
我知道这是一种新方法,但效果很好,哈哈
【讨论】:
谢谢伙计:)。你的建议真的很有帮助【参考方案2】:你很接近,我查看了你的 csv,因为你有一个标题行,我认为使用你的 S.No
作为唯一的任务 ID 可能会很好:
import pandas as pd
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-o', '--option', metavar='', help='-o <option> write either you want to add or view')
# Here I added the action="append"
parser.add_argument('-l', '--select', metavar='', help='-l <used to select the task for modification', action="append")
args = parser.parse_args()
def modify(filename, taskids):
taskids = list(map(int, taskids)) # just to change from str to int for your taskids
df = pd.read_csv(filename, sep=";")
df.loc[df["S.No"].isin(taskids), "Status"] = "complete"
df.to_csv(filename, sep=";", index=False)
modify("csv.csv", args.select)
我正在使用 Pandas 数据框来简化操作。 df.loc[...]
行用于选择其中 S.No 是命令行中给出的任务 ID 之一的每一行,并将状态列更改为“完成”。
我还做了一些我认为您可能会感兴趣的更改:我刚刚在您的解析器中为select
选项添加了一个小的action="append"
。这意味着您将能够通过执行以下操作一次更改多个任务:
python todoarg.py -o modify -l 2 -l 6 -l 3
对于您的option
参数,我建议您在解析器中使用choices
参数:
parser.add_argument(
"-o", "--option",
type = str,
choices = [
"modify",
"add",
"cook_a_turkey"
],
default = "modify", # you can even use a default choice if the parameter is not given
metavar = "",
help = "some help"
)
关于如何根据option
参数的值选择要使用的方法,我认为我没有这样做的好方法,但也许这样的方法可以工作:
my_methods =
"modify": modify, # they keys are the same as provided in the choices in the argument parser
"add": add_task,
"cook_a_turkey": cook_that_turkey,
# And you can call the function like this: However you will have to change a bit your functions to parse the arguments in each of them.
my_methods[parser.option]("csv", args)
# For instance the modify will become:
def modify(filename, args):
taskids = list(map(int, args.select))
# ...
def add_task(filename, args):
# do stuff
def cook_that_turkey(filename, args):
# your grandma recipe
【讨论】:
谢谢,这真的很有帮助,你的所有建议都很棒,我是 python 新手,你的所有建议对我有很大帮助,但我想看看是否有办法在不使用的情况下做到这一点熊猫? 我也用这个方法得到KeyError : 'S.No'
KeyError 表示它没有在字典中找到S.No
条目,在这里您应该将列的名称与您的任务ID 放在您的CSV 中。打印数据框并查看列的名称。另外,也许更改sep=
,我使用了;
,因为这是我在测试中使用的,但您应该改为使用CSV 的字段分隔符。
谢谢 :)..我明白了,但仍然显示缺少位置参数文件名和任务 ID 我必须在其中输入什么?
哦,对了,对于我给出的第一个例子,文件名应该是"csv.csv"
,而taskids应该是args.select
。但是你必须在调用函数时给他们,看看第一个例子的最后一行(我编辑了文件名以匹配你的例子)。以上是关于如何更改 .csv 文件中一行的最后一个值的主要内容,如果未能解决你的问题,请参考以下文章