如何阻止 Tabula 自动删除空列?

How can I stop Tabula from automatically dropping empty columns?

我正在尝试从 PDF 中抓取数据,以便重新格式化它,然后将其插入到 Oracle 中的 table。我正在尝试使用 Tabula 读取 PDF 并将其转换为 tables 的列表,但如果这些列仅包含空值,Tabula 似乎会从 tables 中删除列。 通常这不会是一个问题(数据开始时是 'None',所以我不关心保留它),但是在某些列而不是其他列上删除 'null' 值使得它我的代码不可能识别哪些列是哪些列。 例如,它可能来自:

0   1   2   3

x   x  n/a  x

x   x  n/a  x

x   x  n/a  x

0   1   2

x   x   x

x   x   x

x   x   x

在运行时没有办法知道哪一列被删除了,所以我不能只是将它重新插入到必要的地方。

这些列在数据中没有任何唯一标识符。 我不能只在末尾添加空列,因为 绝对有必要 我在列中保持相同的顺序。

我调查了 Tabula API,虽然我找到了一些关于如何删除空列的实用指南,但我没有找到确保它们保持存在的任何东西。

dflist = tabula.read_pdf(path, pages = '14-27', multiple_tables = True)
# dflist is a list of dataframes
# dflist[0] == a single dataframe

(抱歉格式不佳;不熟悉堆栈溢出间距)

预期结果:

0   1   2   3

X   NaN X   X   

X   NaN X   X   

X   NaN X   NaN

实际结果:

0   1   2

X   X   X   

X   X   X   

X   X   NaN

更新:我能找到的最佳解决方案是调整 'lattice' 设置,该设置决定了如何在 Tabula 中读取 table(您可以在他们的网站上找到文档)。 不幸的是,这些设置也抵消了我 PDF 上的一些行,所以我无法使用它。我不得不放弃让它完全自动化的想法,现在使用暂存 table 人工检查哪些列将被删除。

我遇到了同样的问题,也查看了 GitHub 上的其他示例。我认为每当你避免阅读 headers 和

pandas_options={'header': None}

并且有空栏,这个问题就会显现出来。我测试过让它阅读 headers,但我的 pdf 中的列标题以他们自己的方式混乱,所以这不是一个真正的选择。当您设置 'columns' 和 'area' 参数时似乎不正确,即使没有headers。您准确地告诉它列的位置,如果它们是空的,它仍然会丢弃它们。这可能是白板的缺陷 - 确实 没有什么可以确保它们保持存在。

我也快绝望了,手动做了然后我想出了一个解决方法。

所以和 OP 一样,我也阅读了多个表格,实际上是数百个 pdf 页。在我的情况下,正常的列数是 9,但如果不是 9,则可以预测为 8。此外,它只发生在第 9 列,在原始数据中,这是某些页面上唯一的列完全是空的。因此,对于列表中的数据框,只需在 NaN 的一列上加上 tabula 未能放置的列:

dfs_clean = list()

for df in dflist:
    if df.shape[1] != 9:
        df[8] = np.nan 
        dfs_clean.append(df)       
        continue        
    dfs_clean.append(df)

one_df = pd.concat(dfs_clean)

这仅在它始终是相同的可预测列且有时为空时才有效,因此您可以通过编程方式将其替换为 nans。

如果维护者可以将此功能添加到 tabula 中,或者告诉我们如何使用它(如果它已经存在),那就更好了。 Python 接口有一个 java_options 参数,也许你可以在里面放一些东西来做。

  1. 如果可能,请获取您要抓取的特定 table 的格子版本(即 table,网格线分隔每个单元格,例如 [=81= 的 PDF ] 电子表格)。然后,如果你有格子版本,请尝试在 read_pdf().
  2. 中设置 lattice=True
  3. 如果没有格子版本并且您遇到 table 且单元格之间为空 space,则必须定义 table 列的点坐标边界,以便 Tabula 能够区分空 space 和空列。
  4. 通过查看 https://github.com/tabulapdf/tabula-java/wiki/Using-the-command-line-tabula-extractor-tool#grab-coordinates-of-the-table-you-want 获取 table 列边界的点坐标。有两种可能的获取方式,但您可能要做的是下载 Tabula 应用程序,打开它,然后将您的 PDF 上传到那里。
  5. 而不是 select 在步骤 3 中从 link、select 每一列 one-by-one 写入整个 table 区域,然后按照步骤像往常一样 4 到 5。
  6. 生成的脚本将包含 4 个坐标。获取列(第 2 和第 4)的 x-coordinates 并记下它以备后用。对每一列重复,直到每一列都有 x-coordinates。

例如:

0   1   2   3
    
X   NaN X   X   
    
X   NaN X   X   
    
X   NaN X   NaN
  • 第 0 列 x-coordinates:0、10
  • 第 1 列 x-coordinates:10、20
  • 第 2 列 x-coordinates:20、30
  • 第 3 列 x-coordinates:30、40
  1. 阅读https://tabula-py.readthedocs.io/en/latest/faq.html?highlight=options#can-i-use-option-xxx. The shown example uses the column option, which is documented in https://github.com/tabulapdf/tabula-java/blob/master/README.md如下:

-c,--columns <COLUMNS> x coordinates of column boundaries. Example --columns 10.1,20.2,30.3. If all values are between 0-100 (inclusive) and preceded by '%', input will be taken as % of actual width of the page. Example: --columns %25,50,80.6

  1. 使用您之前记录的列的 x-coordinates 相应地编写列选项,并将其传递到 read_pdf() 中的选项 arg。

例如:

0   1   2   3
    
X   NaN X   X   
    
X   NaN X   X   
    
X   NaN X   NaN
  • 第 0 列 x-coordinates:0、10
  • 第 1 列 x-coordinates:10、20
  • 第 2 列 x-coordinates:20、30
  • 第 3 列 x-coordinates:30、40
col_boundaries = '--columns 10,20,30'
dflist = tabula.read_pdf(path, pages = '14-27', options=col_boundaries)

注意:只有当所有页面的列都位于完全相同的位置时,这才有效。对于具有不同列或布局的页面,您还必须 运行 read_pdf() 使用它们的特定边界。