如何在 Python 中始终如一地将“3.71B”和“4M”等字符串转换为数字?

问题描述 投票:0回答:5

我有一些相当混乱的代码,几乎可以从 Yahoo Finance 为公司生成有形价格/账面(一个名为

ystockquote
的好模块已经获得了无形价格/账面价值)。

我的问题是:

对于计算中的变量之一,已发行股票我得到像 10.89B4.9M 这样的字符串,其中 BM 分别代表 billionmillion。我在将它们转换为数字时遇到问题,这就是我所在的位置:

shares=''.join(node.findAll(text=True)).strip().replace('M','000000').replace('B','000000000').replace('.','') for node in soup2.findAll('td')[110:112]

这很乱,但我认为如果不是

.replace('M','000000').replace('B','000000000').replace('.','') 

我使用的是带变量的正则表达式。我想问题只是哪个正则表达式和变量。其他的建议也不错

编辑:

具体来说,我希望有一些适用于零、一位或两位小数的数字,但这些答案看起来都很有帮助。

python regex finance yahoo-finance
5个回答
20
投票
>>> from decimal import Decimal
>>> d = {
        'K': 3,
        'M': 6,
        'B': 9
}
>>> def text_to_num(text):
        if text[-1] in d:
            num, magnitude = text[:-1], text[-1]
            return Decimal(num) * 10 ** d[magnitude]
        else:
            return Decimal(text)

>>> text_to_num('3.17B')
Decimal('3170000000.00')
>>> text_to_num('4M')
Decimal('4000000')
>>> text_to_num('4.1234567891234B')
Decimal('4123456789.1234000000000')

你也可以

int()
想要的结果


4
投票

将数字解析为浮点数,并使用乘数映射:

multipliers = dict(M=10**6, B=10**9)
def sharesNumber(nodeText):
    nodeText = nodeText.strip()
    mult = 1
    if nodeText[-1] in multipliers:
        mult = multipliers[nodeText[-1]]
        nodeText = nodeText[:-1]
    return float(nodeText) * mult

3
投票
num_replace = {
    'B' : 1000000000,
    'M' : 1000000,
}

a = "4.9M" 
b = "10.89B" 

def pure_number(s):
    mult = 1.0
    while s[-1] in num_replace:
        mult *= num_replace[s[-1]]
        s = s[:-1]
    return float(s) * mult 

pure_number(a) # 4900000.0
pure_number(b) # 10890000000.0

这将适用于像这样的白痴:

pure_number("5.2MB") # 5200000000000000.0

并且由于采用字典方法,您可以以一种易于维护的方式添加任意数量的后缀,并且可以通过以一种大写形式表达字典键然后执行

.lower()
.upper() 来使其更加宽松
使其匹配。


2
投票
num_replace = {
    'B' : 'e9',
    'M' : 'e6',
}

def str_to_num(s):
    if s[-1] in num_replace:
        s = s[:-1]+num_replace[s[-1]]
    return int(float(s))

>>> str_to_num('3.71B')
3710000000L
>>> str_to_num('4M')
4000000

所以

'3.71B'
->
'3.71e9'
->
3710000000L


1
投票

这可能是安全使用评估的机会!! :-)

考虑以下片段:

>>> d = { "B" :' * 1e9', "M" : '* 1e6'}
>>> s = "1.493B"
>>> ll = [d.get(c, c) for c in s]
>>> eval(''.join(ll), {}, {})
1493000000.0

现在把它们放在一个整齐的衬里里:

d = { "B" :' * 1e9', "M" : '* 1e6'}

def human_to_int(s):
    return eval(''.join([d.get(c, c) for c in s]), {}, {})

print human_to_int('1.439B')
print human_to_int('1.23456789M')

回馈:

1439000000.0
1234567.89
© www.soinside.com 2019 - 2024. All rights reserved.