使用列之间的换行符读取csv文件

时间:2019-08-15 16:43:34

标签: python pandas csv dataframe

我已使用pandas读取和解析csv文件,这些列用分号;分隔。有些文件(出于未知原因)在某些列之后有一个'\r\n'序列,这​​使得pandas.read_csv会将它们分成不同的行。我想转义这些字符,然后将“第二行”追加到“第一行”,否则之后解析将变得困难。

我可以识别这些行,因为它们后面是数字,而正确的第一列包含的时间类似于00:00:00。可以使用pandas.read_csv来做到这一点吗?


示例

使用正确的文件,我的代码将如下所示:

data = io.StringIO( ''' a; b; c; d 
                    x10; 20; 30; 40
                    x11; 21; 31; 41
                    x12; 22; 32; 42
                    x13; 23; 33; 43
                    x14; 24; 34; 44
                    x15; 25; 35; 45
                 ''' )

pd.read_csv( data, sep=';' )

输出:

    a   b   c   d
0   10  20  30  40
1   11  21  31  41
2   12  22  32  42
3   13  23  33  43
4   14  24  34  44
5   15  25  35  45

问题

文件损坏的情况如下:

data = io.StringIO( ''' a; b; c; d 
                        x10; 20; 30; 40
                        x11; 21; 31; 41
                        x12; 22; 
                        32; 42
                        x13; 23; 33; 43
                        x14; 24; 34; 44
                        x15; 25; 35; 45
                     ''' )

pd.read_csv( data, sep=';' )

输出:

    a   b   c   d
0   x10     20  30  40.0
1   x11     21  31  41.0
2   x12     22      NaN
3   32  42  NaN     NaN
4   x13     23  33  43.0
5   x14     24  34  44.0
6   x15     25  35  45.0

但是,两种情况下的预期输出都是第一个。在此示例中,我认为在{/ 1}}中将\r\n\d\d替换为\d\d可以消除在熊猫构建数据框之前/期间的那些换行符。

如果可能的话,我想避免先修复文件,避免制作额外的脚本来检查所有文件,然后再读取大熊猫,因为有新文件定期出现。


读取熊猫中的csv文件时是否可以替换字符串的一部分?

还有另一种解决此类问题的方法吗?


使用python 3.6.8,pandas 0.24.2

2 个答案:

答案 0 :(得分:1)

大型csv通常会发生这种情况。解决该问题的方法是使用python读取它们,并检查分隔符的数量是否符合您的期望,否则请删除该行。然后,在更正原始数据后,您可以使用StringIO将其加载到熊猫中。错误示例的示例:

# We load the file
filestream = open(filepath)

# Now we filter the data as follows
data = filter(lambda l: l.count(";")==3, filestream)

# Now we convert to String IO
stream = io.StringIO("\n".join(data))

# And finally we read with Pandas
pd.read_csv(stream, sep=';' )

答案 1 :(得分:0)

我从ivallesp's answer那里得到了零件,并想出了一种解决方案,可以保留虚线。

我将其发布在这里,作为将来我(常常倾向于忘记此类事情)以及其他可能遇到类似问题的文档。


错误的文件,带有虚线

$userId = 2; // id of chris

$sql = <<<SQL
    UPDATE u
    SET u.vehicle_desc = v.vehicle
    FROM users u
        INNER JOIN vehicles v ON v.id = u.vehicle_id
    WHERE u.id = ?
SQL;
\DB::statement($sql, [$userId]);

变化

在磁盘中有一个实际文件(不是infile = io.StringIO( ''' a; b; c; d x10; 20; 30; 40 x11; 21; 31; 41 x12; 22; 32; 42 x13; 23; 33; 43 x14; 24; 34; 44 x15; 25; 35; 45 ''' ) # The lines are joined with a \n, and whitespace stripped data = '\n'.join( [ item.strip() for item in infile ] ) # Now data is not a file stream, but a string, with \n s in between #Search for occurrences of newline + NOT(x + number) and just keep # found group data = re.sub( '\n(?!x\d\d)', '\1', data ) # Now data is a file stream again data = io.StringIO( data ) # Fed to pandas.read_csv pd.read_csv( data, sep=';' ) 的情况下,我必须进行少量修改,删除io.StringIO,不知道为什么。除此之外,它也可以在不添加任何内容的情况下起作用(.strip())。

最后,我的实际文件在第一列中有时间,格式为''.join(...)00:00,依此类推。所以我实际上是这样使用的:

00:05