【问题标题】:Python: How to ignore comments only at the beginning of the line of a file to get the clean Panda DataFramePython:如何仅忽略文件行开头的注释以获取干净的 Panda DataFrame
【发布时间】:2021-03-13 10:02:37
【问题描述】:

我有一个目录中的 .ASC 数据文件被另一个程序写入其中,数据看起来像这样

数据在多个文件中,其中 cmets 以“/”开头,标题在文件中出现多次,但我只想为所有数据行保留一个标题。

最终目标是在将整个数据文件写入目录后立即将其加载到 Pandas Dataframe 中。我只在一个文件上尝试过简单的 Pandas read_csv

import pandas as pd
df=pd.read_csv("demo.txt", header = None, sep = "\s+",comment='/')
df.head()

得到如下结果:

后来我尝试使用传统的 python 读取文件操作,该操作有效,但部分您可以看到它跳过了很多行。

f = open("demo.txt", "r")
for i in f:
    if not (f.readline(1)=='/'):
        f2 = open("demofile2.txt", "a")
        f2.write(f.readline())
    
f2.close()

the algorithm could be:
read one file or multiple files or as soon as a new file written into the directory
read it directly as .ASC if not change to . TXT a
keep the headers in the first row and discard all the comments.

注意:我已手动将类型 .ASC 更改为 .TXT,

更新:尝试添加可以在本地复制粘贴的较小数据集

/comments start

/comments end
/id h1  h2  h3  Date        h5
0   1   41  0   12/4/2018   0
1   1   0   0   12/4/2018   0
2   1   0   0   12/4/2018   0
3   1   0   0   12/4/2018   0
4   1   90  0   12/4/2018   0
/comments start

/comments end                   
/id h1  h2  h3  Date        h5
5   1   41  0   12/4/2018   0
6   1   0   0   12/4/2018   0
7   1   0   0   12/4/2018   0
8   1   0   0   12/4/2018   0
9   1   90  0   12/4/2018   0

希望它看起来像这样:

id  h1  h2  h3  Date        h5
0   1   41  0   12/4/2018   0
1   1   0   0   12/4/2018   0
2   1   0   0   12/4/2018   0
3   1   0   0   12/4/2018   0
4   1   90  0   12/4/2018   0
5   1   41  0   12/4/2018   0
6   1   0   0   12/4/2018   0
7   1   0   0   12/4/2018   0
8   1   0   0   12/4/2018   0
9   1   90  0   12/4/2018   0

注意这个模式在文件中重复了好几次,即 cmets,->headers->data cmets->headers->data 等等。并且目录中有多个文件。

【问题讨论】:

  • 请注意,您的日期中也有/,这就是pandas.read_csv 不适合您的原因
  • 是的,这就是为什么我尝试了另一种方法,首先只在开头删除“/”,然后将其转换为 pandas 数据框,但问题是这种方法跳过了很多行
  • 您能否提供一个表格的复制粘贴示例(图像对此无用)?然后我们可以自己尝试一下。
  • @Thymen 实际上试图找到一种方法来放置 csv 或 .asc 数据,但我在这个问题中找不到任何方法来加载它
  • @awaisumar 您能否将图像示例作为代码块提供(如果以下答案尚未解决您的问题)?

标签: python-3.x pandas data-science


【解决方案1】:

您的第二种方法是在正确的轨道上,但我认为调用readline(1) 正在读取一个字节并且当您进行后续调用时,您没有得到完整的行。此外,文件句柄f2 被多次重新分配给打开的文件;它真的应该在重新分配之前关闭,或者更好的是,它应该在每次调用中重复使用,直到你完成。可能存在您的某些写入未刷新到磁盘的问题。

这样的事情应该允许您重新格式化输入的 CSV,以便删除所有以 / 开头的行。

with open("input.txt") as csv, open("output.txt", "w") as out:
    for line in csv:
        if not line.startswith("/"):
            out.write(line)

【讨论】:

  • 以更简洁的方式解决了部分问题,您认为这种方式也适用于较大的文件吗?我怎样才能保留第一个标题并跳过其余部分,实际上所有标题也以注释符号开头
  • 我对您的文件知之甚少,无法确定如何确定哪些行包含标题。如果您知道标题列名称,您可以使用names kwarg 将它们传递给read_csv(仍然保留您的header=None):pandas.pydata.org/pandas-docs/stable/reference/api/…
【解决方案2】:

这是一个可能的解决方案,可能不是最干净的解决方案:

import pandas as pd

headers = None
results = []
with open('input.asc', 'r') as file:
    for line in file.readlines():
        skip_comments = False
        if line.startswith('/comments start'):
            skip_comments = True
            continue

        if line.startswith("/comments end"):
            skip_comments = False
            continue

        if line.strip() and not skip_comments:
            if line.startswith("/"):
                headers = [word for word in line[1:].strip().split(' ') if word]
                headers = list(map(str.strip, headers))
            else:
                results.append([word for word in line.strip().split(' ') if word])

df = pd.DataFrame(results, columns=headers)
print(df)

输出:

  id h1  h2 h3       Date h5
0  0  1  41  0  12/4/2018  0
1  1  1   0  0  12/4/2018  0
2  2  1   0  0  12/4/2018  0
3  3  1   0  0  12/4/2018  0
4  4  1  90  0  12/4/2018  0
5  5  1  41  0  12/4/2018  0
6  6  1   0  0  12/4/2018  0
7  7  1   0  0  12/4/2018  0
8  8  1   0  0  12/4/2018  0
9  9  1  90  0  12/4/2018  0

说明

由于 cmets 有一定的开始和结束顺序,我将它们用作开始和停止信号以跳过其间的行。

然后我注意到对于包含标题的行总是以 / 开头的模式,我将其用作检查标题的过滤器,我正在使用手动解析:

headers = [word for word in line[1:].strip().split(' ') if word]
headers = list(map(str.strip, headers))

第一行收集整个单词,这意味着当列名包含空格时它不起作用,例如Date entered。您必须手动转换这些情况。

否则我假设它是一个数据列,并使用以下方法手动解析它们:

results.append([word for word in line.strip().split(' ') if word])

缺点与标题相同,如果数据无论如何使用空格都会中断。

注意事项:

  • 我将文件重命名为 input.asc,而不是 .txt,因为这并不重要。
  • 标题或数据中的任何项目都不能包含' '(空格),否则解析将不成功,并且您最终会得到比标题更多的列。

【讨论】:

  • 这也是一个不错的方法,在删除 cmets 按照上述解决方案中的建议写入新文件,然后使用 pandas 数据框读取文件后,我得到了类似的结果。缺点是我必须为目录中的每个文件创建一个新文件,并对列进行硬编码。所以你的解决方案也是一个不错的方法。非常感谢您的宝贵时间
猜你喜欢
  • 2017-07-26
  • 1970-01-01
  • 2020-05-25
  • 2012-05-05
  • 2015-12-04
  • 1970-01-01
  • 2013-07-23
  • 1970-01-01
  • 2015-12-22
相关资源
最近更新 更多