Python:读取 Windows 生成的 csv,其中列中有回车符 return

Python: Reading a Windows generated csv with carriage return in column

我正在开发一个 Python 程序,该程序需要读取在 Windows 2012 服务器计算机上生成的 csv 文件。出于数据质量原因,Python 代码的目的是为数据中的每一列提供 min/max。所以我无法更改源数据。

数据文件的分隔符是|-|。是的,它是一个多字符定界符。数据编码为 latin-1。最近我发现一些列可以有回车 returns。我也必须在我的程序中处理它。

以下是数据示例:

123456781|-|!|-|04/08/2022 00:00:00|-|04/22/2022 00:00:00|-|04/08/2022 00:00:00|-|2|-|987654|-|12|-|12345|-|D|-|J|-|N|-|12.3400|-|0.0000|-|0.0000|-|1.2300|-|12345.6700|-|J|-|N|-|J|-|N|-||-|23.4500|-|J|-|04/06/2022 11:00:00|-|ABC001      |-||-||-|0.0000
123456782|-|"|-|04/19/2022 00:00:00|-|05/02/2022 00:00:00|-|04/19/2022 00:00:00|-|2|-|456789|-|12|-|
98765|-|D|-|J|-|N|-|6.7800|-|0.0000|-|0.0000|-|6.7800|-|12345.6700|-|J|-| |-|J|-| |-||-|6.7800|-|J|-|04/19/2022 10:00:00|-|JOHNDOE|-||-||-|0.0000
123456785|-|"|-|04/17/2022 00:00:00|-|05/01/2022 00:00:00|-|04/17/2022 00:00:00|-|11|-|0|-|0|-||-|D|-|N|-|N|-|0.0000|-|0.0000|-|0.0000|-|8.7600|-|54321.1200|-|N|-|N|-|J|-|N|-||-|0.0000|-|N|-|04/15/2022 13:45:00|-|ABC001      |-||-||-|0.0000
123456787|-|'|-|04/20/2022 00:00:00|-|05/03/2022 00:00:00|-|04/19/2022 00:00:00|-|2|-|345678|-|12|-|87654|-|D|-|J|-|N|-|4.7800|-|0.0000|-|0.0000|-|4.7800|-|34567.8900|-|J|-| |-|J|-| |-||-|4.7800|-|J|-|04/20/2022 10:00:00|-|DEF003|-||-||-|0.0000

这里看不到,但是123456782开头的那一行,|-|12|-|后面有一个回车return在 98765|-|D| 之前.在带有“显示行尾”符号的 Notepad++ 中,它在这些值之间显示 CR,并且所有行都以 CRLF 结尾。

当我用Pandas read_csv读取这个数据时,它把第二行的后半部分当作一个新行。我尝试了 lineterminator 参数的不同设置。没有骰子。 lineterminator="\n"、lineterminator="\r" 和 lineterminator="\r\n" 都产生相同的结果。

示例 Pandas read_csv 我使用的语句:

import pandas as pd
import re

csvfile = "D:\Data\file_20220412.dat"
separator = "|-|"
separator = re.escape(separator)
df = pd.read_csv(csvfile, sep=separator, header="infer", encoding="latin-1", lineterminator="\n")

所以同事建议改用csv.reader。第一个问题:不允许使用多字符定界符!但是我们可以通过替换来解决这个问题:

data = csv.reader((line.replace('|-|', ',') for line in csvfile), delimiter=",")

然后奇怪的事情发生了。它在 29 列中正确读取了一些数据,但有些行放在 2 列中。如您所见,某些行在第二列中包含双引号。当您使用 csv.reader 读取数据然后将其写入输出文件时,结果会添加额外的双引号。这使得其余代码将其视为 2 列。

"123456785|-|""|-|04/17/2022 00:00:00|-|05/01/2022 00:00:00|-|04/17/2022 00:00:00|-|11|-|0|-|0|-||-|D|-|N|-|N|-|0.0000|-|0.0000|-|0.0000|-|8.7600|-|54321.1200|-|N|-|N|-|J|-|N|-||-|0.0000|-|N|-|04/15/2022 13:45:00|-|ABC001      |-||-||-|0.0000"

我真的希望我不必做某种正则表达式解决方案来解决引入的额外双引号问题 csv.reader。

我正在寻找两种可能的解决方案:

  1. (我更喜欢)让 Pandas read_csv 停止将回车 return 解释为换行符。
  2. 使 csv.reader 停止添加额外的双引号。

有什么想法吗?

我找到了可能的解决方案。我设法打开 Python 中的文件,没有任何 csv 处理,这取代了回车 returns。 newline="\n" 使得选择分隔符旁边的 \r 字符成为可能。

separator="|-|"
data = open(csvfile, "r", encoding="latin-1", newline="\n")
data = data.read()
data = re.sub(r"\|\-\|[\r]", separator, data)
data = re.sub('\|\-\|', ',', data)
print(data)

现在我可以把它放在 read_csv 中,它应该被视为一个普通的 csv 文件。

也许我什至不必扫描分隔符旁边的回车 returns(因为现在我意识到它们不必总是出现在该列中)。

我下周再试试。

您可以先使用正则表达式解析出额外的回车 return 字符,然后使用 Pandas.

的 multi-character 分隔符
import pandas as pd
import io
import re
import csv

with open('e_carriagereturn_20220430.dat', newline='') as f_input:
    data = re.sub('\x0d[^\x0a]', ' ', f_input.read())
    df = pd.read_csv(io.StringIO(data), sep='\|-\|', quoting=csv.QUOTE_NONE, engine='python', header=None)

print(df)

或者,如果没有正则表达式,您可以 pre-parse 数据如下。使用 newline='' 模式来保留换行符。这些可以很容易地删除。其次使用 quoting=csv.QUOTE_NONE 禁用报价处理。最后删除只用 -.

看到的任何列
import pandas as pd
import io
import csv

rows = []

with open('e_carriagereturn_20220430.dat', newline='') as f_input:
    data = f_input.read().replace('\x0d', '')
    csv_input = csv.reader(io.StringIO(data), delimiter='|', quoting=csv.QUOTE_NONE)
    
    for row in csv_input:
        rows.append([value for value in row if value != '-'])
        
df = pd.DataFrame(rows)        
print(df)

两者都给出类似的输出:

            0  1                    2                    3                    4   5        6   7               8  9  10 11        12      13      14       15            16 17 18 19 20 21        22 23                   24             25 26 27      28
0   752296019  "  04/15/2022 00:00:00  04/28/2022 00:00:00  04/15/2022 00:00:00  13        0   0                  A  J  J    0.0000  0.0000  0.0000   1.2300   123456.2700  J     J        -23.4500  N  04/19/2022 12:00:41  AEINSTEIN1           0.0000
1   752296020  "  03/31/2022 00:00:00  04/13/2022 00:00:00  03/31/2022 00:00:00   1   359542  12       318047.01  A  J  J  543.2100  0.0000  0.0000  32.1000   244680.4400  J     J        543.2100  J  04/01/2022 12:44:42       PKDICK1         0.0000
2   752296032  !  04/08/2022 00:00:00  04/22/2022 00:00:00  04/08/2022 00:00:00   2   222856  12           54321  A  J  N   26.8700  0.0000  0.0000   1.2800    38068.8800  J  N  J  N      26.8700  J  04/06/2022 12:00:32   ABC003              0.0000
3   752296044  "  04/19/2022 00:00:00  05/02/2022 00:00:00  04/19/2022 00:00:00   2   222857  12           34877  D  J  N    6.7800  0.0000  0.0000   6.7800   122345.3500  J     J          6.7800  J  04/19/2022 12:00:49        WGIBSON        0.0000
4   752296098  !  04/17/2022 00:00:00  05/01/2022 00:00:00  04/17/2022 00:00:00  13        0   0                  D  N  N    0.0000  0.0000  0.0000   8.7000    79689.4800  N  N  J  N       0.0000  N  04/15/2022 12:24:58   ABC003              0.0000
5   431807560  "  04/12/2022 00:00:00  04/21/2022 00:00:00  04/12/2022 00:00:00   5        0   0                  D  J  N   16.9600  0.0000  0.0000   0.8500    10919.6900  J     J         16.7800  N  04/13/2022 14:49:44     FHERBERT          0.0000
6   431807563  !  04/17/2022 00:00:00  05/01/2022 00:00:00  04/17/2022 00:00:00  11        0   0                  D  N  N    0.0000  0.0000  0.0000   2.6700    31790.1600  N  N  J  N       0.0000  N  04/15/2022 12:44:56   ABC003              0.0000
7   431807594  "  03/28/2022 00:00:00  04/11/2022 00:00:00  03/28/2022 00:00:00   1   580807  12  12345AB12345AB  D  J  J  193.8200  0.0000  0.0000  19.3800   276921.4800  J     J        193.8200  J  03/29/2022 12:00:38        WGIBSON        0.0000
8   431807597  "  04/19/2022 00:00:00  05/02/2022 00:00:00  04/19/2022 00:00:00   1   107348  12     12.45671/AB  D  J  J    6.7800  0.0000  0.0000   6.7800    87133.8200  J     J          6.7800  J  04/15/2022 12:22:35      UKLEGUIN         0.0000
9   679785779  "  03/18/2022 00:00:00  04/01/2022 00:00:00  03/18/2022 00:00:00  13        0   0                  B  N  N    0.0000  0.0000  0.0000   9.3300   142940.7700  N  N  J  N       0.0000  N  04/20/2022 08:04:02     AHUXLEY           0.0000
10  679785789  !  04/15/2022 00:00:00  04/29/2022 00:00:00  04/15/2022 00:00:00   2  4876321  12       488250/CD  D  J  N  876.5800  0.0000  0.0000  16.7800   200604.8900  J  N  J  N     876.5400  J  04/13/2022 12:28:49   ABC003              0.0000
11  665661904  !  04/15/2022 00:00:00  04/29/2022 00:00:00  04/15/2022 00:00:00   2   394132  12        46409 EF  D  J  N  567.9800  0.0000  0.0000   9.1600   513561.4600  J  N  J  N     567.8700  J  04/13/2022 12:24:37   ABC003              0.0000
12  665661909  "  03/25/2022 00:00:00  04/01/2022 00:00:00  03/25/2022 00:00:00  14   216308  12      97745894XY  D  J  J    0.0000  0.0000  0.0000  11.4500   208666.1300  J     J          0.0000  J  03/25/2022 12:25:03     FHERBERT          0.0000
13  665661934  !  04/19/2022 00:00:00  05/02/2022 00:00:00  04/19/2022 00:00:00   2   627911  12     abc/21.4177  D  J  N   54.3200  0.0000  0.0000  23.4500   333689.0000  J  N  J  N      54.3200  J  04/14/2022 23:15:20   ABC003              0.0000
14  665661945  !  03/25/2022 00:00:00  04/07/2022 00:00:00  03/25/2022 00:00:00   1  3074312  12      923088/ABC  D  J  J  199.2600  0.0000  0.0000  14.5600   850785.1500  J  N  J  N     189.0120  J  03/25/2022 11:48:55   ABC003              0.0000
15  665661965  !  04/22/2022 00:00:00  05/06/2022 00:00:00  04/22/2022 00:00:00   1   627921  12           27160  D  J  J  567.3400  0.0000  0.0000  45.6800  2252133.2900  J  N  J  N     567.3400  J  04/20/2022 12:43:09   ABC003              0.0000
16  665661976  !  04/22/2022 00:00:00  05/06/2022 00:00:00  04/22/2022 00:00:00   2   627942  12       1734793zy  D  J  N  223.4800  0.0000  0.0000  23.4500   416715.9100  J     J        234.5600  J  04/21/2022 12:04:19   ABC003              0.0000
17  665661978  !  04/29/2022 00:00:00  05/13/2022 00:00:00  04/29/2022 00:00:00   2   627998  12        44524 fg  D  J  N  226.3000  0.0000  0.0000   5.3700   162912.0800  J  N  J  N     234.2000  J  04/21/2022 12:12:44   ABC003              0.0000
18  665661987  "  04/07/2022 00:00:00  04/19/2022 00:00:00  04/07/2022 00:00:00  14        0   0                  D  J  J   78.6500  0.0000  0.0000   1.3400    56249.8400  N     J         78.6500  N  04/08/2022 12:32:28       PKDICK1         0.0000