【问题标题】:Python Pandas df, best way to replace $, M and K in currency amount to change to intPython Pandas df,将货币金额中的$,M和K替换为int的最佳方法
【发布时间】:2021-08-25 17:17:18
【问题描述】:

我正在做一个练习熊猫的个人项目,还有美丽的汤,我把这个信息刮下来,把它放在熊猫 df 中,如下所示:

0        €8.5M
1           €0
2        €9.5M
3          €2M
4         €21M
         ...  
16534    €1.8M
16535    €1.1M
16536    €550K
16537    €650K
16538    €1.1M
Name: Value, Length: 16539, dtype: object
0        €67K
1          €0
2        €15K
3        €11K
4        €13K
         ... 
16534     €3K
16535     €2K
16536     €2K
16537     €7K
16538     €3K
Name: Wage, Length: 16539, dtype: object  

所以为了分析这些信息,我想清理这些数据并将其转换为整数,我能想到的是:

df['Wage'] = df['Wage'].apply(lambda x: re.sub('€','',x))
df['Wage'] = df['Wage'].apply(lambda x: re.sub('K','000',x))

df['Value'] = df['Value'].apply(lambda x: re.sub('€','',x))
df['Value'] = df['Value'].apply(lambda x : re.sub('M','00000',x) if (('M' in x) and ('.' in x))else x)
df['Value'] = df['Value'].apply(lambda x : re.sub('[.]','',x))
df['Value'] = df['Value'].apply(lambda x : re.sub('M','000000',x))
df['Value'] = df['Value'].apply(lambda x : re.sub('K','000',x))

df['Wage'] = df['Wage'].astype(int)
df['Value'] = df['Value'].astype(int)

我首先替换了货币符号,然后检查点,以便我可以将 M 替换为 5 个零,然后将剩余的 M 替换为 6 个零,然后将 K 替换为 3 个零,然后我将类型更改为 int。 但我觉得这不是一个好方法,你怎么看?有什么更好的方法来做到这一点?我尝试创建一个函数,但做不到。

【问题讨论】:

    标签: python regex pandas dataframe


    【解决方案1】:

    更新的解决方案:

    新解决方案:仅使用 .replace()astype()
    不依赖 pd.eval 进行公式评估:

    您可以将MK 转换为指数格式的相应幅度:

    K 转换为科学计数法的e+03

    M 转换为科学计数法的e+06

    (支持integerfloat 任何小数位数

    然后,将科学计数形式的文本转换为浮点类型,然后转换为整数以获得最终所需的格式,如下所示:

    df['Value'] = df['Value'].replace({'€': '', ' ': '', 'M': 'e+06', 'K': 'e+03'}, regex=True).astype(float).astype(int)
    

    输入数据:

             Value
    0        €8.5M
    1           €0
    2        €9.5M
    3          €2M
    4         €21M
    16534    €1.8M
    16535    €1.1M
    16536    €550K
    16537    €650K
    16538    €1.1M
    

    输出:

    print(df)
    
              Value
    0       8500000
    1             0
    2       9500000
    3       2000000
    4      21000000
    16534   1800000
    16535   1100000
    16536    550000
    16537    650000
    16538   1100000
    

    旧解决方案:

    您可以将MK 转换为公式,然后使用pd.eval 计算数值。

    K转换为公式* 1000

    M转换为公式* 1000000

    通过这种方式,我们可以支持带有任意数量小数点的基值(带或不带小数点以及小数部分的长度)。我们可以从小数点后所有长度的小数部分的公式中得到正确的结果。

    df['Value'] = df['Value'].str.replace('€', '')
    df['Value'] = df['Value'].str.replace('M', ' * 1000000')
    df['Value'] = df['Value'].str.replace('K', ' * 1000')
    df['Value'] = df['Value'].map(pd.eval).astype(int)
    

    或者在一行中简化代码,感谢@MustafaAydın 的建议:

    df['Value'] = df['Value'].replace({"€": "", "M": "*1E6", "K": "*1E3"}, regex=True).map(pd.eval).astype(int)
    

    结果:

    print(df)
    
    
              Value
    0       8500000
    1             0
    2       9500000
    3       2000000
    4      21000000
    16534   1800000
    16535   1100000
    16536    550000
    16537    650000
    16538   1100000
    

    输入样本数据如下:

             Value
    0        €8.5M
    1           €0
    2        €9.5M
    3          €2M
    4         €21M
    16534    €1.8M
    16535    €1.1M
    16536    €550K
    16537    €650K
    16538    €1.1M
    

    在最后一步之前,我们得到:

                   Value
    0      8.5 * 1000000
    1                  0
    2      9.5 * 1000000
    3        2 * 1000000
    4       21 * 1000000
    16534  1.8 * 1000000
    16535  1.1 * 1000000
    16536     550 * 1000
    16537     650 * 1000
    16538  1.1 * 1000000
    

    然后我们将其提供给pd.eval 以对其进行评估并转换为数值(浮点数),然后我们可以进一步将其转换为整数。

    【讨论】:

    • +1;如果您愿意,可以用 dict 替换 df.Value.replace({"€": "", "M": "*1E6", "K": "*1E3"}, regex=True)(并将 pd.eval 包裹起来);但也许你的更具可读性。
    • @MustafaAydın 这也是一种很好的替代方法。谢谢!
    • 谢谢!,我不知道 "*100000" 公式,它解决了我的浮动问题,我不知道 dict 替换,这将使 mi 代码更短,感谢两者!
    • @LuisGan 很高兴为您提供帮助!请记得accept and upvote解决方案:-)
    • 我注意到的一件事是,这会使过程变慢,你知道为什么吗?
    【解决方案2】:

    您可以使用以下方法替换一个正则表达式 Series.str.replace() 传递中的值

    import pandas as pd
    df = pd.DataFrame({'Value':['€8.5M', '€0','€9.5M','€2M','€21M','€1.8M','€1.1M','€550K','€650K','€1.1M']})
    
    def repl(x):
        if not x.group(2):
            return x.group(1)
        if x.group(2) == 'K':
            return str(int(float(x.group(1)) * 1000))
        else:
            return str(int(float(x.group(1)) * 1000000))
    
    >>> df['Value'].str.replace(r'^€?(\d+(?:\.\d+)?)([KM])?$', lambda x: repl(x), regex=True).astype(int)
    0     8500000
    1           0
    2     9500000
    3     2000000
    4    21000000
    5     1800000
    6     1100000
    7      550000
    8      650000
    9     1100000
    Name: Value, dtype: int32
    

    ^€?(\d+(?:\.\d+)?)([KM])?$ 正则表达式匹配

    • ^ - 字符串开头
    • €? - 一个可选的
    • (\d+(?:\.\d+)?) - 第 1 组:一位或多位数字,然后是 . 和一位或多位数字的可选序列
    • ([KM])? - 可选组 2:KM
    • $ - 字符串结束。

    如果没有 KM,则返回 Group 1 值。如果有K,则第1组中的数字乘以1000,否则乘以1000000。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-15
      • 2020-11-26
      • 1970-01-01
      • 2021-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多