我有一个 SAP 生成的文件,其中包含许多列和一些不需要的行。我应该如何直接读入 Pandas?

Posted

技术标签:

【中文标题】我有一个 SAP 生成的文件,其中包含许多列和一些不需要的行。我应该如何直接读入 Pandas?【英文标题】:I have a SAP generated file with many columns and some unwanted rows. How should I read directly into Pandas? 【发布时间】:2016-01-04 12:02:20 【问题描述】:

我的桌子:

Table To Be Searched MSEG
Number of hits                                                            273208
Maximum No. of Entri                                                           0
Runtime                00:24:17

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|Mat. Doc. |MatYr|MvT|Material |Plnt|SLoc|Batch     |Customer|  Amount in LC|        Amount|    Quantity|BUn|    Qty in UnE|EUn|PO        |MatYr|Mat. Doc. |Order    |Profit Ctr|SLED/BBD  |Pstng Date|Entry Date|Time    |User name  |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|4912693062|2015 |551|100062   |HDC2|0001|5G30MC1A11|        |         9.03 |         9.06 |      0.083 |CS |            2 |EA |          |     |          |         |IN1165B085|26.01.2016|01.08.2015|01.08.2015|01:13:16|O33462     |
|4912693063|2015 |501|166      |HDC2|0004|          |        |         0.00 |         0.00 |          2 |EA |            2 |EA |          |     |          |         |IN1165B085|          |01.08.2015|01.08.2015|01:13:17|O33462     |
|4912693320|2015 |551|101343   |HDC2|0001|5G28MC1A11|        |        53.73 |        53.72 |      0.500 |CS |           12 |EA |          |     |          |         |IN1165B085|25.01.2016|01.08.2015|01.08.2015|01:16:30|O33462     |
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Table To Be Searched MSEG
Number of hits                                                            273208
Maximum No. of Entri                                                           0
Runtime                00:24:17

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|Mat. Doc. |MatYr|MvT|Material |Plnt|SLoc|Batch     |Customer|  Amount in LC|        Amount|    Quantity|BUn|    Qty in UnE|EUn|PO        |MatYr|Mat. Doc. |Order    |Profit Ctr|SLED/BBD  |Pstng Date|Entry Date|Time    |User name  |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|4912696602|2015 |344|100399   |HMH3|0001|5G29MH3S11|        |         0.00 |         0.00 |      9,061 |CS |        9,061 |CS |          |     |          |         |IN1165B074|26.01.2016|01.08.2015|01.08.2015|01:54:15|A70475     |

它包含超过 100 万行。以前,我首先使用以下 Python 代码将此文件转换为 CSV:

def hasNumbers(inputString):
    return any(char.isdigit() for char in inputString)

with open("Input.txt") as infile:
    for line in infile:
        with open("Out.csv", "a") as myfile:
            if line[:1] == '|':
                if hasNumbers(line) == True:
                    newline = line[1:-2].replace(' ','')
                    newline.translate(None, ",!.;")
                    myfile.write(newline+'\n')

有没有更好的方法将这种文件转换为 CSV 格式,或者我应该如何直接将其解析为 pandas?

【问题讨论】:

抱歉,您的示例数据格式与您发布的一样吗?即多个表使用----| 来分隔列和行? 是的,我的示例数据与原始数据相同,但它们之间有很多行 ***.com/a/58269521/11262633中的答案不需要打开文本文件两次。 【参考方案1】:

您可以使用itertools.ifilter 仅过滤表数据并使用csv.reader 来解析重要行,如下所示:

import csv
import itertools
import StringIO

with open('input.txt', 'rb') as f_input:
    for line in itertools.ifilter(lambda x: len(x) > 2 and x[0] == '|' and x[1].isalpha(), f_input):
        header = [cols.strip() for cols in next(csv.reader(StringIO.StringIO(line), delimiter='|', skipinitialspace=True))][1:-1]
        break

with open('input.txt', 'rb') as f_input, open('output.csv', 'wb') as f_output:
    csv_output = csv.writer(f_output)
    csv_output.writerow(header)
    for line in itertools.ifilter(lambda x: len(x) > 2 and x[0] == '|' and x[1] != '-' and not x[1].isalpha(), f_input):
        csv_input = csv.reader(StringIO.StringIO(line), delimiter='|', skipinitialspace=True)
        csv_output.writerow([col.strip().translate(None, ",!.;") for col in next(csv_input)[1:-1]])

这将为您提供如下输出 csv 文件:

Mat. Doc.,MatYr,MvT,Material,Plnt,SLoc,Batch,Customer,Amount in LC,Amount,Quantity,BUn,Qty in UnE,EUn,PO,MatYr,Mat. Doc.,Order,Profit Ctr,SLED/BBD,Pstng Date,Entry Date,Time,User name
4912693062,2015,551,100062,HDC2,0001,5G30MC1A11,,903,906,0083,CS,2,EA,,,,,IN1165B085,26012016,01082015,01082015,01:13:16,O33462
4912693063,2015,501,166,HDC2,0004,,,000,000,2,EA,2,EA,,,,,IN1165B085,,01082015,01082015,01:13:17,O33462
4912693320,2015,551,101343,HDC2,0001,5G28MC1A11,,5373,5372,0500,CS,12,EA,,,,,IN1165B085,25012016,01082015,01082015,01:16:30,O33462
4912696602,2015,344,100399,HMH3,0001,5G29MH3S11,,000,000,9061,CS,9061,CS,,,,,IN1165B074,26012016,01082015,01082015,01:54:15,A70475

【讨论】:

你在第四行得到了“”。该文件不应包含任何 ,因为在解析它时会出现 EOF 错误。 如果列包含逗号,CSV 格式会自动添加引号,否则将被解释为另一列。您可以强制引用所有列,但要抑制它们,您需要解析逗号。此文件将按原样正确加载到 Excel 中。 如果可能的话,您能否在顶部添加一行标题。 如果我们的 csv 文件中有 ",那么在将文件解析为 pandas 时会出现此错误:CParserError: Error tokenizing data. C error: Expected 1 fields in line 73685, saw 4 感谢您的回答,但还有一个请求您的第一个程序已正确解析。对此感到抱歉,但您没有从给我错误的行中删除"'。感谢您的解决方案。如果可能的话,你能告诉我我应该改变什么,以便脚本将删除"' 并在顶部添加一组标题。我得到的错误在第 73685 行,因为有 "。谢谢【参考方案2】:

这里是基于How to convert a SAP .txt extraction into a .csv file中答案的方法,不需要打开输入文件两次。

这是来自该答案的代码,使用 @Martin Evans 的巧妙技术测试 row[1].isalpha 以确定您是否有标题,并且只导出一次:

import csv

ii = 0

with open('file.txt', 'r', encoding='utf8', newline='') as f_input, \
     open(str(ii + 1) + 'output.csv', 'w', encoding='utf8', newline='') as f_output:

    input_lines = filter(lambda x: len(x) > 2 and x[0] == '|' and x[1] == ' ', f_input)

    csv_input = csv.reader(input_lines, delimiter='|')
    csv_output = csv.writer(f_output)

    found_header = False
    for row in csv_input:
        if not found_header and row[1].isalpha():
            found_header = True
        csv_output.writerow(col.strip() for col in row[1:-1])

【讨论】:

以上是关于我有一个 SAP 生成的文件,其中包含许多列和一些不需要的行。我应该如何直接读入 Pandas?的主要内容,如果未能解决你的问题,请参考以下文章

列和行操作 Python Pandas

为 SQL 插入语句生成日志文件

SQL 动态列和更新多列

如何使用 Docker 配置 SAP SNC

用于多个项目的通用 Wix 安装程序

在 Python 中,如何生成数组的排列,其中每一列和每一行只有一个元素?