【问题标题】:Read Relative Lines in a text document and convert to Pandas DF读取文本文档中的相对行并转换为 Pandas DF
【发布时间】:2018-08-06 16:11:53
【问题描述】:

使用 Python 3.6 读取文本文件以提取 relative 行以转换为 pandas 数据帧。

工作原理:在文本文档中搜索短语并将该行转换为 pandas df。

import pandas as pd
df = pd.DataFrame()
list1 = []
list2 = []

with open('myfile.txt') as f:
    for lineno, line in enumerate(f, 1):
        if 'Project:' in line:
            line = line.strip('\n')
            list1.append(repr(line))

# Convert list1 into a df column
df = pd.DataFrame({'Project_Name':list1})

什么不起作用:根据搜索结果返回相对行。在我的情况下,我需要将“相对”行 -6 到 -2(在本文前面)存储为 Pandas 列。

with open('myfile.txt') as f:
    for lineno, line in enumerate(f, 1):
        if 'Project:' in line:
            list2.append(repr(line)-6)  #<--- can't use math here

返回:TypeError:不支持的操作数类型 -: 'str' 和 'int'

还尝试使用部分成功的范围:

with open('myfile.txt') as f:
    for lineno, line in enumerate(f, 1):
        if 'Project' in line:
            all_lines = f.readlines()
            required_lines = [all_lines[i] for i in range(lineno-6,lineno-2)]
            print (required_lines)
            list2.append(required_lines)  #<-- does not work

Python 将打印前 4 行目标行,但它似乎无法将其保存为列表或循环遍历文本文档中“项目”的每个发现。有没有更好的方法来保存搜索词上方(或下方)的相对行的结果?非常感谢。

文本数据如下:

0  Exhibit 3
1  Date: February 2018
2  Description
3  Description
4  Description
5  2015
6  2016
7  2017
8  2018
9  $100.50    <----  Add these as different dataframe columns
10 $120.33    <----
11 $135.88    <----
12 $140.22    <----
13 Project A
14
15 Exhibit 4
16 Date: February 2018
17 Description
18 Description
19 2015
20 2016
21 2017
22 2018
23 $899.25    <----
24 $901.00    <----
25 $923.43    <----
26 $1002.02   <----
27 Project B

【问题讨论】:

  • 如果您可以发布您的输入数据的样子以及您希望输出的样子会有所帮助。
  • 添加了文本的示例,感谢 Alex

标签: pandas search python-3.6


【解决方案1】:

这可能会奏效,它确实假设在“项目”行之前总是有四个值。

>>> a = []
>>> with open('test.txt') as f:
...     prev_lines = []
...     for line in f:
...         prev_lines.append(line.strip('\n'))
...         if 'Project' in line:
...             a.append(prev_lines[-5:])
...             del prev_lines[:]
>>> df = pd.DataFrame(a, columns=list('ABCDi'))
>>> df
         A        B        C         D          i
0  $100.50  $120.33  $135.88   $140.22  Project A
1  $899.25  $901.00  $923.43  $1002.02  Project B

或者不包含项目:

>>> a = []
>>> with open('test.txt') as f:
...     prev_lines = []
...     for line in f:
...         prev_lines.append(line.strip('\n'))
...         if 'Project' in line:
...             a.append(prev_lines[-5:-1])
...             del prev_lines[:]
>>> df = pd.DataFrame(a, columns=list('ABCD'))
>>> df
         A        B        C         D
0  $100.50  $120.33  $135.88   $140.22
1  $899.25  $901.00  $923.43  $1002.02

【讨论】:

  • 比我的最新版本好很多,这是我第一次在同一个块中看到两次“prev_lines = []”列表构造。从来没想过。
  • 我已经更新了代码以使用更好的方法来清除前面的行列表。当我对一个包含 2000 条记录的文件进行测试时,它运行得非常快。
  • 有没有办法前进4列?我试过 a.append(next_lines[:4]) 但它跳过了第一个实例。
  • 我不确定我是否完全理解,您的意思是从project 开始访问这些行吗?此方法有效,因为输入是重复的,但可以实现。让我知道它应该包括哪些具体的行。
  • Alex - 是的,我们让前 4 行工作,但现在我正试图让 NEXT 4 行进入 pandas df。所以在上面的例子中,当搜索“项目”时,它会返回:(空白),展览 4,日期:2018 年 2 月,描述。
【解决方案2】:

您的第二个解决方案不起作用的原因是因为您正在使用类似对象的生成器(在您的情况下为f)读取文件,它完成对文件的迭代将停止。

您的迭代for lineno, line in enumerate(f, 1): 旨在在文件内逐行迭代,但以一种内存有效的方式,一次只读取一行。当您找到匹配的行时,all_lines = f.readlines() 会消耗生成器。当for lineno, line in enumerate(f, 1): 中的下一次迭代被调用时,它会引发StopIterationError,从而导致循环停止。

如果您先读取文件的全部内容然后迭代该列表,则可以使您的第二个解决方案工作。

如果你想提高内存效率,你可以维护一个FIFO queue所需的行数。

【讨论】:

  • 尝试使用 relative_line = f.readlines(), Line6 = [relative_line[lineno - 6]]。也不工作。我没有正确使用 f.readlines()。
猜你喜欢
  • 1970-01-01
  • 2020-06-12
  • 1970-01-01
  • 2018-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多