【问题标题】:Cleaning a messy CSV using python, saving in excel works使用python清理凌乱的CSV,保存在excel中
【发布时间】:2018-07-02 10:11:47
【问题描述】:

我对使用 python 很陌生,我试图将 CSV 文件的负载(100 秒)读入一个数据帧。但是,csv 文件非常混乱,使用多个分隔符等。我试着搜索这个网站,但我发现的所有东西都不起作用。我已经尝试了许多选项的 readlines 和 pd.read,但我得到的只是错误或空数据帧。当我在 excel 中打开 CSV 时,它看起来很好,当我将它保存为 UTF-8 csv 时,一切正常。但是,即使使用宏,对每个 excel 文件执行此操作也是如此。有没有办法使用python代码复制这个过程,例如in2csv?下面我提供了我需要使用的 csv 文件的一部分,以及来自 excel 的部分 csv(有效)。对我来说,主要区别似乎是空格和逗号分隔符,但在 pd.read 中更改它并没有帮助。非常感谢!

凌乱的 csv:

"Device name:UU-WGB-JV_1  Device type:SUN2000  Device address:IP Address=62.72.193.88   Device No.=2  Date:2018-01-23 08:51:23  "   
"Generated On"  "Device Status" "Energy Yield of Current Day (kWh)" "Inv. efficiency"(%)    "Total Energy Yield (kWh)"  "Input Power (kW)"  "Active Power (kW)" "Reactive Power (kVar)" "Power Factor"  "Grid Frequency (Hz)"   "Grid A Current (A)"    "Grid B Current (A)"    "Grid C Current (A)"    "Grid A Phase Voltage (V)"  "Grid B Phase Voltage (V)"  "Grid C Phase Voltage (V)"  "PV1 Input Current (A)" "PV2 Input Current (A)" "PV3 Input Current (A)" "PV4 Input Current (A)" "PV5 Input Current (A)" "PV6 Input Current (A)" "PV1 Input Voltage (V)" "PV2 Input Voltage (V)" "PV3 Input Voltage (V)" "PV4 Input Voltage (V)" "PV5 Input Voltage (V)" "PV6 Input Voltage (V)" "Cabinet Temperature (℃)"   
"2017-12-22 00:00:00    "   "Idle: No irradiation"  "0.00"  "0.00"  "45803.34"  "0.000" "0.000" "0.000" "0.000" "0.00"  "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"
"2017-12-22 00:15:00    "   "Idle: No irradiation"  "0.00"  "0.00"  "45803.34"  "0.000" "0.000" "0.000" "0.000" "0.00"  "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"   "0.0"

好的 CSV:

Device name:UU-CB_1  Device type:SUN2000  Device address:IP Address=62.140.137.136   Device No.=1  Date:2018-01-22 13:31:51  ,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Generated On,Device Status,Energy Yield of Current Day (kWh),Inv. efficiency(%),Total Energy Yield (kWh),Input Power (kW),Active Power (kW),Reactive Power (kVar),Power Factor,Grid Frequency (Hz),Grid A Current (A),Grid B Current (A),Grid C Current (A),Grid A Phase Voltage (V),Grid B Phase Voltage (V),Grid C Phase Voltage (V),PV1 Input Current (A),PV2 Input Current (A),PV3 Input Current (A),PV4 Input Current (A),PV5 Input Current (A),PV6 Input Current (A),PV1 Input Voltage (V),PV2 Input Voltage (V),PV3 Input Voltage (V),PV4 Input Voltage (V),PV5 Input Voltage (V),PV6 Input Voltage (V),Cabinet Temperature (℃)
"2017-11-01 00:00:00    ",Idle: No irradiation,0,-,36670.07,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

【问题讨论】:

  • 第一个是定长文件,不是CSV。 Excel 可以很好地猜测格式,但会失败,例如,如果您在使用 , 作为小数点分隔符和 ; 作为列表分隔符的欧洲国家工作。
  • 对于混乱的 CSV 和多个分隔符,是的。这正是数据工程和数据科学的意义所在——80% 正在清理数据。例如,即使是“好”的 CSV 也有混乱的日期。 Inv. efficiency(%) 字段中的 - 是什么?还是 header 中的许多 ,,, 条目?看起来有人试图将标题视为列行。您必须为每个文件指定适当的格式(平面、分隔等),并在适当的地方跳过标题。
  • 为避免指定多种格式,一个技巧是将尽可能多的文件转换为通用格式。例如,在定长文件中,您可以将所有 " " 实例转换为 "," 或很少使用的字符,如 ¤。不过,您必须对此进行广泛测试并保留备份副本以防出错。例如,平面文件头似乎有 不同的个空格。
  • - 表示没有价值。我主要对当天的能源产量感兴趣,所以这没问题。当我在这个文件上使用 pd.read_csv(file, header = 1, index_col = 'Generated On',parse_dates = True) 时,它对我来说非常可行。所以我必须将固定长度(或宽度)转换为 csv 文件?它会自动保存为 .csv。

标签: python pandas csv encoding utf-8


【解决方案1】:

对于初学者来说,这是一种更直观的处理大型 csv 文件的方法。这允许您一次处理多组行或块。

import pandas as pd
chunksize = 10 ** 8
for chunk in pd.read_csv(filename, chunksize=chunksize):
    process(chunk)

您可能想在这里查看,http://pandas.pydata.org/

Pandas 是一个高性能的大数据数据分析库。

【讨论】:

    【解决方案2】:

    似乎第一行(标题)是不可挽救的,因为它包含空格和未加引号的字段。可以通过特定的正则表达式修复。我会跳过它。

    其余行不是 csv,而是包含用空格分隔的引号标记,shlex.split 轻而易举:

    import shlex,csv
    
    with open("input.csv") as f:
       title = next(f)   # discard title line
    
       with open("output.csv","w",newline="",encoding="utf-8") as fw:
          cw = csv.writer(fw,delimiter=";")  # may be changed to ","
          cw.writerows(shlex.split(l) for l in f)
    

    输出:

    Generated On;Device Status;Energy Yield of Current Day (kWh);Inv. efficiency(%);Total Energy Yield (kWh);Input Power (kW);Active Power (kW);Reactive Power (kVar);Power Factor;Grid Frequency (Hz);Grid A Current (A);Grid B Current (A);Grid C Current (A);Grid A Phase Voltage (V);Grid B Phase Voltage (V);Grid C Phase Voltage (V);PV1 Input Current (A);PV2 Input Current (A);PV3 Input Current (A);PV4 Input Current (A);PV5 Input Current (A);PV6 Input Current (A);PV1 Input Voltage (V);PV2 Input Voltage (V);PV3 Input Voltage (V);PV4 Input Voltage (V);PV5 Input Voltage (V);PV6 Input Voltage (V);Cabinet Temperature (℃)
    2017-12-22 00:00:00    ;Idle: No irradiation;0.00;0.00;45803.34;0.000;0.000;0.000;0.000;0.00;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0
    2017-12-22 00:15:00    ;Idle: No irradiation;0.00;0.00;45803.34;0.000;0.000;0.000;0.000;0.00;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0
    

    文件现在可以在 excel 中正常打开(注意各种版本的 excel 默认需要逗号或分号分隔符)

    【讨论】:

    • 第一个文件是定长文件。它实际上更容易和更安全地阅读。第二个文件也好不到哪里去 - 检查 - 是否存储在百分比列中
    • 我相信您的专业知识。只是提供一种使用标准 python 库解析它的简单方法。
    • 现在试试这个。我已使用我的“杂乱”CSV 文件之一作为 input.csv,但如何查看输出?
    • 别在意我的最后一个问题,但是当我尝试在数据帧中打开输出时,我会看到一个充满 NaN 的帧。此外,这个框架的形状没有意义。
    • 我只是提供了一种以正确格式获取 csv 的方法。作为 csv 它可以正常打开(除了需要返工的日期,因为 excel 错误地检测到它)
    【解决方案3】:

    您可以将 csv 文件作为字符串读取,然后使用正则表达式来处理拆分。通常,字段分隔符是逗号、分号或制表符,而一行以 \n 结尾,因此读取可能如下所示:

    import re
    
    data = []
    with open("yourfile.csv", "r") as csvfile:
        for line in csvfile:
            data.append(re.split("[\,\;\t\n]", line)[:-1])
    

    现在 data 是包含您的数据的列表列表,这些数据应该很容易转换为数据框或其他任何东西。我在 split 中包含了 \n ,因为在我的测试中,行尾仍然是行的一部分。这只是一个示例,毫无疑问您会希望从中创建一个函数并使其适应您的用例。

    【讨论】:

    • 这给了我一些奇怪的东西,也许它与编码有关。这是我得到的一个例子: [['ÿþ"\x00D\x00e\x00v\x00i\x00c\x00e\x00 \x00n\x00a\x00m\x00e\x00:\x00U\x00U\x00-\x00C\x00B \x00_\x002\x00 \x00 \x00D\x00e\x00v\x00i\x00c\x00e\x00 \x00t\x00y\x00p\x00e\x00:\x00S\x00U\x00N\x002\等等
    • 是的,这肯定是编码问题。我认为您的问题更多是跨文件出现不同的分隔符。 open() 使用的默认编码取决于平台(更多信息here),但可以通过关键字指定。加encoding="utf-8"可以吗?
    • 显然它是 utf-16 编码的。 pd.read_csv 现在可以工作了。谢谢!
    【解决方案4】:

    所以这主要是一个编码问题。我使用了一个名为 cpconverter 的 .exe 将编码从 unicode (1200) 更改为 utf-8。现在 pd.read 在我通过 sep='\t' 时工作。如果我可以使用 python 脚本(或使用原始编码)更改此编码会更好,但现在它可以工作。感谢所有的努力和帮助!

    编辑:将 encoding = 'utf-16' 传递给 pd.read_csv 现在可以修复所有问题。不知道我是怎么错过的,但原始编码显然是 utf-16。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-21
      • 1970-01-01
      • 2018-05-02
      • 1970-01-01
      • 1970-01-01
      • 2019-11-29
      • 1970-01-01
      相关资源
      最近更新 更多