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

Posted

技术标签:

【中文标题】熊猫将数字转换为字符串 - 意外结果【英文标题】:Pandas converting numbers to strings - unexpected results 【发布时间】:2018-04-29 21:23:54 【问题描述】:

似乎没有办法将输入表(从 html / xls / etc 文件)获取到 DataFrame 对象,因为它是一对一的,没有 pandas 内部应用的任何字段转换。

假设下面的 html 表以 .xls 文件的扩展名保存,我们如何在 Python 内存中获得该表与 DataFrame 对象的相同表示?

“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。我认为这个逻辑包括语言环境设置,可能是熊猫内部的一些规则等。直接指定字符串转换器不允许获取初始值。

(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.read_* 的“十进制”和“千”参数的规范看起来不是一个可靠的解决方案,因为它适用于所有字段。简单示例:它可以将 "02.2017" 格式的日期字段视为数字,并将其转换为 "022017"

【问题讨论】:

我猜read_html 应该像read_csv 那样采用dtype 参数。 @Goyo,不幸的是它没有......有an issue on Pandas GitHub and it is still open &lt;td class="tDetail"&gt;,,,2,,,,5,,,,,5,,,,0,,,.,,,7,,,7,,,&lt;/td&gt; 的输入值(注意!)也转换为2550.77 @Goyo,对于 Pandas 0.21.0,它给了我TypeError: read_html() got an unexpected keyword argument 'dtype' 我删除了processing 标签,因为它是用于名为Processing 的编程语言,而不是涉及文件处理的程序的通用标签。使用前请阅读标签说明。 【参考方案1】:

这行得通吗?

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'

【讨论】:

【参考方案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)

【讨论】:

以上是关于熊猫将数字转换为字符串 - 意外结果的主要内容,如果未能解决你的问题,请参考以下文章

如何在熊猫中将 4 位数字转换为小时:分钟时间格式

将一列字符串转换为熊猫列表

将字符串的所有字母字符转换为熊猫数据框中单独列中的整数

TypeScript:字符串转换为数字

PHP和JavaScript将字符串转换为数字string2int

离子: - 将字符串转换为纬度,经度在末尾追加更多数字?