Python 熊猫:使用用户更正的错误值导入csv

Python 熊猫:使用用户更正的错误值导入csv,python,csv,pandas,user-input,converters,Python,Csv,Pandas,User Input,Converters,我尝试导入csv并处理错误的值,例如,错误的十进制分隔符或int/double列中的字符串。我使用转换器进行错误修复。对于数字列中的字符串,用户会看到一个输入框,必须在其中固定值。是否可以获取实际“导入”的列名和/或行?如果没有,有没有更好的方法 example csv: ------------ description;elevation point a;-10 point b;10,0 point c;35.5 point d;30x from PyQt4 import QtGui im

我尝试导入csv并处理错误的值,例如,错误的十进制分隔符或int/double列中的字符串。我使用转换器进行错误修复。对于数字列中的字符串,用户会看到一个输入框,必须在其中固定值。是否可以获取实际“导入”的列名和/或行?如果没有,有没有更好的方法

example csv:
------------
description;elevation
point a;-10
point b;10,0
point c;35.5
point d;30x


from PyQt4 import QtGui
import numpy
from pandas import read_csv

def fixFloat(x):
    # return x as float if possible
    try:
        return float(x)
    except:
        # if not, test if there is a , inside, replace it with a . and return it as float
        try:
            return float(x.replace(",", "."))
        except:
            changedValue, ok = QtGui.QInputDialog.getText(None, 'Fehlerhafter Wert', 'Bitte korrigieren sie den fehlerhaften Wert:', text=x)
            if ok:
                return self.fixFloat(changedValue)
            else:
                return -9999999999

def fixEmptyStrings(s):
    if s == '':
        return None
    else:
        return s

converters = {
    'description': fixEmptyStrings,
    'elevation': fixFloat
}

dtypes = {
    'description': object,
    'elevation': numpy.float64
}

csvData = read_csv('/tmp/csv.txt',
    error_bad_lines=True,
    dtype=dtypes,
    converters=converters
)

如果您想迭代它们,内置的
csv.DictReader
非常方便。我写了这个函数:

import csv
def read_points(csv_file):

    point_names, elevations = [], []
    message = (
        "Found bad data for {0}'s row: {1}. Type new data to use "
        "for this value: "
    )

    with open(csv_file, 'r') as open_csv:
         r = csv.DictReader(open_csv, delimiter=";")
         for row in r:
             tmp_point = row.get("description", "some_default_name")
             tmp_elevation = row.get("elevation", "some_default_elevation")

             point_names.append(tmp_point)            
             try:
                 tmp_elevation = float(tmp_elevation.replace(',', '.'))
             except:
                 while True:
                     user_val = raw_input(message.format(tmp_point, 
                                                         tmp_elevation))

                     try:
                         tmp_elevation = float(user_val)
                         break
                     except:
                         tmp_elevation = user_val

             elevations.append(tmp_elevation)                

    return pandas.DataFrame({"Point":point_names, "Elevation":elevations})
对于四行测试文件,它给出了以下内容:

In [41]: read_points("/home/ely/tmp.txt")
Found bad data for point d's row: 30x. Type new data to use for this value: 30
Out[41]: 
   Elevation    Point
0      -10.0  point a
1       10.0  point b
2       35.5  point c
3       30.0  point d

[4 rows x 2 columns]
显示一个完整的QT对话框对于这个任务来说似乎有点过分了。为什么不只是一个命令提示符?您还可以添加更多的转换函数,并将一些东西(如分隔符)更改为关键字参数(如果您希望它更具自定义性)


一个问题是有多少数据需要迭代。如果是大量数据,这将非常耗时和乏味。在这种情况下,您可能只想放弃像“30x”这样的观察值,或者将它们的点ID名称写入其他文件,这样您就可以返回并在Emacs或VIM之类的东西中一次性处理它们,在这里,一次处理大量文本将更容易。

我将采用不同的方法。
而不是在读取csv时,我会天真地读取csv并然后修复/转换为浮点:

In [11]: df = pd.read_csv(csv_file, sep=';')

In [12]: df['elevation']
Out[12]:
0     -10
1    10,0
2    35.5
3     30x
Name: elevation, dtype: object
现在,只需遍历此列:

In [13]: df['elevation'] = df['elevation'].apply(fixFloat)

这将使您更容易对代码进行推理(您将函数应用于哪些列,如何访问其他列等)。

您可以使用
df['elevation']=df['elevation']=aType(float)
将这些值中的大多数转换为浮点数,您的问题是值“30x”应该是什么?30x是一个意外设置为数字列的字符串的示例值。因为很难说实际值是什么样子,用户应该选择或修复它。如果有大量数据,并且如果某些不正确的格式意味着拒绝该数据,那么加载后处理它将非常低效。如果需要修改的比例很高,这也比在读取数据时在同一个单通道上调整数据的效率低得多。@EMS不确定我是否同意你使用“非常”和“很多”,我会给你“可能”。。。通常,使用更快的c引擎从csv读取数据要比使用较慢的python引擎(如果使用python函数,则必须使用较慢的python引擎)更快。我同意,如果坏数据的比例很高,而您想要拒绝它,那么一次完成就更节省空间。。。但这似乎是一个不寻常的案例tbh.Idk。想象一下,如果需要清理或预处理truefx中的.csv数据。每月有7亿行,即使是需要预处理的一小部分数据,也会让情况变得很糟糕,即使您一次只读取一个数据块的所有数据块。当然,当你达到这个规模时,你可能需要转移到一个合适的数据库,但仍然有人试图阅读这种东西。我想我更愿意使用Python中的文件生成器。但我同意你的观点,在很多情况下,通过“过度计算”来加载所有内容并没有那么有害。