Pandas将数字转换为字符串-意外结果

8

似乎没有办法直接将输入表格(来自html / xls /等文件)转换为DataFrame对象,因为pandas内部没有应用任何字段转换。

假设以下HTML表格以.xls文件扩展名保存,我们如何使用DataFrame对象在Python内存中获得相同的表示形式?

"test_file.xls"的内容:

<body>
    <table>
        <thead>
            <tr>
                <th class="tabHead" x:autofilter="all">Number</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td class="tDetail">1.320,00</td>
            </tr>
            <tr>
                <td class="tDetail">600,00</td>
            </tr>
        </tbody>
    </table>
</body>

(1) 文件的直接读取

处理代码:

import pandas

df = pandas.read_html('test_file.xls')
print(df[0])
print(df[0].dtypes)

输出:

     Number
0      1.32
1  60000.00

Number    float64
dtype: object

我们可以看到,这些数字是按照一些预定义的逻辑转换成了float64类型。我认为这个逻辑包括本地设置、pandas内部的一些规则等等。直接指定字符串转换器无法获得初始值。

(2) 对每个维度应用str函数作为转换器

处理代码:

converters = {column_name: str for column_name in df[0].dtypes.index}
df = pandas.read_html(f, converters = converters)
print(df[0])
print(df[0].dtypes)

输出:

    Number
0  1.32000
1    60000

Number    object
dtype: obje

显然,此问题的预期输出为:
     Number
0  1.320,00
1    600,00

有时候会出现一个文件包含以不同格式(美国/欧洲等)输入的数字的情况。这些数字的小数点、千位分隔符等不同。因此,处理这种文件的逻辑方式是将数据“原样”提取为字符串,并使用正则表达式/其他模块分别对每一行进行解析。在pandas中有没有办法做到这一点?还有其他处理这种文件的方法吗?谢谢大家!
备注:针对pandas.read_*的“decimal”和“thousands”参数的说明似乎不是一个可靠的解决方案,因为它适用于所有字段。快速例子:它可以将日期字段转换为数字,例如将“02.2017”格式转换为“022017”。

我猜 read_html 应该像 read_csv 一样接受一个 dtype 参数。 - Stop harming Monica
2
@Goyo,不幸的是它并没有...在Pandas GitHub上有一个问题,而且它仍然没有解决。 (https://github.com/pandas-dev/pandas/issues/10534) - MaxU - stand with Ukraine
<td class="tDetail">,,,2,,,,5,,,,,5,,,,0,,,.,,,7,,,7,,,</td>(注意点!)的输入值也转换为2550.77 - Pleeea
@Goyo,对于Pandas 0.21.0,它给了我一个TypeError: read_html() got an unexpected keyword argument 'dtype' - MaxU - stand with Ukraine
如果您有格式为100.000,00的数字值和日期为01.12.2017,则解决方法如下:在read_html调用中使用decimal = ','thousands = '.'并传递转换器字典,将所有列映射到str:converters = {column_name: str for column_name in df[0].dtypes.index}。这样,数字将是正确的(根据此格式),日期不会更改为类似于1122017的东西(请记住,前导零可能会被删除!) - Pleeea
显示剩余3条评论
2个回答

2

您必须指定千位分隔符和小数点分隔符。这对我有用:

import pandas as pd

html = """
<body>
    <table>
        <thead>
            <tr>
                <th class="tabHead" x:autofilter="all">Number</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td class="tDetail">1.320,00</td>
            </tr>
            <tr>
                <td class="tDetail">600,00</td>
            </tr>
        </tbody>
    </table>
</body>
"""

df = pd.read_html(html, decimal=",", thousands=".")
print(df)

0

这个可以工作吗?

import pandas as pd


with open('test_file.xls') as f:
    raw_html = f.read()


raw_html = raw_html.replace('"tDetail">', """tDetail">'""").replace('</td>', "'</td>")


df = pd.read_html(raw_html)

返回

       Number
0  '1.320,00'
1    '600,00'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接