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