【问题标题】:Truncate numbers to 3 decimal places in CSV file while ignoring strings将 CSV 文件中的数字截断为小数点后 3 位,同时忽略字符串
【发布时间】:2018-01-16 16:08:01
【问题描述】:

所以我有一个包含大量数字和单词的 CSV 文件,我需要将数字截断到小数点后三位,但到目前为止我尝试过的所有操作都不起作用,因为字符串:我收到一个错误留言说 '无法将字符串转换为浮点数'。

我使用了这里建议的代码:format to 3 decimal places all decimal number in csv file python

并得到了那个错误。

代码看起来像(假设所有缩进都是正确的):

with open('metaanalysis_data.csv', 'rb') as f_input, 
open('metaanalysis_datas.csv', 'wb') as f_output:
    csv_input = csv.reader(f_input, quotechar="'")
    csv_output = csv.writer(f_output)
    csv_output.writerow(next(csv_input))

    for cols in csv_input:
        for i in cols:
            for i in xrange(1, 10):
            #if i != str:
                cols[i] = '{:.3f}'.format(float(cols[i]))
        csv_output.writerow(cols)

我尝试添加:

if i is float:

在 'for i in xrange(1, 10)' 之前,然后我尝试了同样的事情,它清除了我的错误消息,但导致文件根本没有被修改。

请帮忙!谢谢!

【问题讨论】:

  • 您可以使用if not isinstance(cols[i], str):,但我建议您阅读索引和数据类型,因为您的语法已关闭(您遇到了更大的问题)。您在循环中使用了两次i,即使这是正确的,测试i 的type 也没有意义,因为那只是您的索引变量。此外,您正在读取和写入同一个文件,这绝对是糟糕的。最后,我们不能只是“假设所有缩进都是正确的。”
  • 添加您建议的行不会导致错误消息,但也不会导致我的小数被四舍五入或截断。此外,如果您更仔细地查看代码,您会看到我正在读取和写入两个不同的文件。我之所以这么说是关于缩进,是因为我不知道如何在缩进完整的情况下复制和粘贴,并且我想明确指出缩进不是问题。
  • 你是对的——当我注意到文件名不同时,编辑我的帖子已经太晚了。然而,缩进对 python 来说很重要——你可以使用空格手动将它们添加到你的帖子中。你能提供一个小样本输入和所需的输出吗?

标签: python csv decimal


【解决方案1】:

在 Python 中使用 pandas,您应该可以这样完成:

# load pandas package
import pandas as pd

# read in initial file
dataset = pd.read_csv('metaanalysis_data.csv')

# create function that tries to round input to three decimal places,
# returns input if failure occurs (e.g. if not a float)
def try_cutoff(x):

    try:
        return round(float(x), 3)
    except Exception:
        return x

# loop over each column and apply try_cutoff to each element in each column
for field in dataset.columns:


    dataset[field] = dataset[field].map(try_cutoff)

# write new dataset result to CSV file
dataset.to_csv("some_new_file.csv", index = False)

因此,这实际上创建了一个函数 try_cutoff,它将尝试将元素四舍五入到小数点后三位。如果它碰到一个字符串,那么它只会返回那个字符串。然后,您在数据框中的每一列上运行它,并将新的数据框写入文件。

如果这对你有用,请告诉我。

【讨论】:

  • 谢谢;这工作得很好。之后我是否必须关闭文件,还是会自动关闭?
  • 运行“dataset.to_csv”行时连接会自动关闭,所以你不用担心。
  • 我喜欢这个答案,因为它维护了值的 float 数据类型。使用'{:.3f}'.format() 将数字转换为字符串,因此,它们将被写入文件,并在数字周围加上引号。
【解决方案2】:

问题在于 CSV 中只有一些值是浮点数,但对于其余的值,转换将失败。你可以试试:

with open('metaanalysis_data.csv', 'rb') as f_input, 
open('metaanalysis_datas.csv', 'wb') as f_output:
    csv_input = csv.reader(f_input, quotechar="'")
    csv_output = csv.writer(f_output)
    csv_output.writerow(next(csv_input))

    for row in csv_input:
        for i, elem in enumerate(row):
            try:
                row[i] = '{:.3f}'.format(float(elem))
            except ValueError: pass
        csv_output.writerow(row)

这样,当转换失败时,它会引发 ValueError 异常,而元素 row[i] 将保持原样。

【讨论】:

  • @pault 哎呀,谢谢,你说得对,我复制粘贴了原始的 sn-p 没有太多阅读,只更改了相关部分(有趣的是,代码无论如何都做了同样的事情,只是重复了更多的事情...)。我修复了它并改进了一点。
  • 所以我尝试了这个,但它只导致最后一行数据被写入并且无法弄清楚为什么会发生这种情况。我尝试在原始代码中只使用“尝试”,但它确实像你说的那样重复了一些事情。
  • @birdoptera 只写了最后一行,因为缩进不正确(考虑到我们对您原始问题的交流,这很讽刺)。最后一行应该缩进,以便将输出写入 inside for 循环。缩进在python中很重要!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-25
  • 1970-01-01
  • 2018-04-12
  • 1970-01-01
  • 1970-01-01
  • 2021-07-03
  • 1970-01-01
相关资源
最近更新 更多