【问题标题】:Pandas to_csv script modifying numbers to long float numbers when it shouldn't bePandas to_csv 脚本将数字修改为不应该的长浮点数
【发布时间】:2013-11-23 14:58:44
【问题描述】:

下面的 pandas 脚本会不断修改我导出到 CSV 的数据,而这是不应该的。 如果您将原始文件与修改后的testing2.csv 进行比较,您会看到第一行的0.357 之类的数字变成:0.35700000000000004 而在第2 行,0.1128 的数字根本没有改变。 .

应该修改这些数字,它们都应该保持原样。

testing.py

import re
import pandas
# each block in the text file will be one element of this list
matchers = [[]]
i = 0 
with open('testing.txt') as infile:
    for line in infile:
        line = line.strip()
        # Blocks are seperated by blank lines
        if len(line) == 0:
            i += 1
            matchers.append([])
            # assume there are always two blank lines between items 
            # and just skip to the lext line
            infile.next()
            continue
        matchers[i].append(line)


# This regular expression matches the variable number of students in each block
studentlike = re.compile('(\d+) (.+) (\d+/\d+)')
# These are the names of the fields we expect at the end of each block
datanames = ['Data', 'misc2', 'bla3']
# We will build a table containing a list of elements for each student
table = []
for matcher in matchers:
    # We use an iterator over the block lines to make indexing simpler
    it = iter(matcher)
    # The first two elements are match values
    m1, m2 = it.next(), it.next()
    # then there are a number of students
    students = []
    for possiblestudent in it:
        m = studentlike.match(possiblestudent)
        if m:
            students.append(list(m.groups()))
        else:
            break
    # After the students come the data elements, which we read into a dictionary
    # We also add in the last possible student line as that didn't match the student re
    dataitems = dict(item.split() for item in [possiblestudent] + list(it))
    # Finally we construct the table
    for student in students:
        # We use the dictionary .get() method to return blanks for the missing fields
        table.append([m1, m2] + student + [dataitems.get(d, '') for d in datanames])

textcols = ['MATCH2', 'MATCH1', 'TITLE01', 'MATCH3', 'TITLE02', 'Data', 'misc2', 'bla3']
csvdata = pandas.read_csv('testing.csv')
textdata = pandas.DataFrame(table, columns=textcols)

# Add any new columns
newCols = textdata.columns - csvdata.columns
for c in newCols:
    csvdata[c] = None

mergecols = ['MATCH2', 'MATCH1', 'MATCH3']
csvdata.set_index(mergecols, inplace=True, drop=False)
textdata.set_index(mergecols, inplace=True,drop=False)
csvdata.update(textdata)
csvdata.to_csv('testing2.csv', index=False)

testing.csv

testing.txt

MData (N/A)
DMATCH1
3 Tommy 144512/23332
1 Jim 90000/222311
1 Elz M 90000/222311
1 Ben 90000/222311
Data $50.90
misc2 $10.40
bla3 $20.20


MData (B/B) 
DMATCH2
4 James Smith 2333/114441
4 Mike 90000/222311
4 Jessica Long 2333/114441
Data $50.90
bla3 $5.44

有人知道如何解决这个问题吗?

(上面的例子100%完美地重现了这个问题。我花了很长时间才找出导致这个问题的原因。)

【问题讨论】:

    标签: python python-2.7 csv pandas


    【解决方案1】:

    这看起来像是一个精度问题。

    尝试更改您的to_csv 行以包含参数float_format='%.4f',它将四舍五入到小数点后两位。

    【讨论】:

    • 问题是我有一些小浮点数(1dp 或 2dp),我希望它们保持 1 或 2dp。
    【解决方案2】:

    Pandas 支持两种基本的数字类型,Int64 和 Float64。 Float64 不会精确地表示十进制值,因为它是浮点类型。您的选择是

    1. 按照@TomAugspurger 的建议指定float_format(这可以按列或整个数据框完成
    2. 将列数据类型转换为对象

    选项 2 可以这样完成:

    df['col_name'] = df['col_name'].astype(object)
    

    【讨论】:

    • 选项 2 似乎对我不起作用,您能在我的示例中使用它吗?
    • 您的示例未在我的环境中运行: Traceback(最近一次调用最后一次):文件“testing.py”,第 41 行,在 dataitems = dict(item.split() for [possiblestudent] + list(it)) 中的项目 ValueError:字典更新序列元素 #2 的长度为 3; 2 是必需的
    • 不知道为什么,一定和\r\n的有关系
    【解决方案3】:

    试试这个:)

    csvdata = pandas.read_csv('testing.csv', dtype={'TITLE5' : 'object', 'TITLE5.1' : 'object', 'TITLE5.2' : 'object', 'TITLE5.3' : 'object'})
    

    【讨论】:

    • 将数字存储为对象似乎不是一个具有前瞻性的解决方案。除非您打算将这些数字视为字符串,从不使用它们的实际值,否则您最好使用将它们视为浮点数的解决方案。 @TomAugspurger 的解决方案似乎是一个更好的折衷方案。
    • @DanAllan 他的选项对我不起作用,这个选项有效,你真的不应该拒绝一个有效的答案。
    • 他真的投了反对票吗?只有当我试图帮助某人实际上不是试图帮助某人时,投反对票才是合理的......
    • 在我看来,将数值数据作为对象加载是一个非常糟糕的主意,尤其是出于美观的原因。如果您尝试对该数据使用数值函数,您会遇到经常出现在这里的this confusing numpy bug。我用我的反对票来取消推广这种有问题的方法;让 AEA 的声誉受损并不是重点。我感谢 AEA 的诚意,并承认他的回答可能对某人有用,即使我在这种情况下不同意。取消投票为时已晚。
    • @DanAllan 如果他编辑了他的帖子,您可以将其转为赞成或不投票。但是,回到有问题的问题,TomAugspurger 提供的代码不符合我的需求,因为它还将我的一些列有 8 个小数位浮点数或我的有 1 或 2 个小数点浮点数的列变为 4 个小数位浮点数,转换为 mattexx 显示在我的代码中没有任何作用(我无法得到他所说的工作)......那么还有哪些其他解决方案?
    猜你喜欢
    • 2018-02-24
    • 2016-08-10
    • 2018-03-17
    • 2020-02-08
    • 1970-01-01
    • 2019-05-26
    • 2016-03-31
    • 2016-04-17
    相关资源
    最近更新 更多