pandas - pandas 或 postgres 表 - 如何转换字符串货币值,例如“£300k”
问题描述
我有一个带有当前格式化为字符串的货币字段的表,例如“150 万英镑”。如何将列转换为等效的数值,即 1,500,000?
数据在 postgres 中,因此我可以将其转换为表格,或使用 pandas 进行转换。我目前正在尝试使用熊猫。理想情况下,我想了解如何做到这一点。
我试过使用 pandas to_numeric
,但它无法解析该值。
import pandas as pd
d = {'id': [1, 2, 3, 4],
'name': ["A", "B", "C", "D"],
'assets': ["£472.96k", "£142.6m", "£500", "-£3.38m"]}
df = pd.DataFrame(data=d)
df['assets'] = pd.to_numeric(['assets'])
编辑 - 下面的代码适用于熊猫。
不过会对 postgres 方法感兴趣
def convert_column(Col):
Col = Col.str.replace('£', '')
Col = (Col.replace(r'[km]+$', '', regex=True).astype(float) * \
Col.str.extract(r'[\d\.]+([km]+)', expand=False)
.fillna(1)
.replace(['k','m'], [10**3, 10**6]).astype(int))
return Col
for col in ['assets']:
df[col] = convert_column(df[col])
解决方案
Postgres 解决方案是完全可行的,它需要 1 个 SQL 语句。下面实现这样的解决方案。该查询假定输入字符串数组。然后开始显示每个步骤(通过子选择)以得出资产价值。
- 将数组分离(取消嵌套)为单个元素。
- 丢弃货币符号 (£)。
- 通过正则表达式拆分出数值和幅度 (k,m) 代码。
- 将幅度代码应用于最终值的数值。
- 一路上,保留原始值,最后如果不是有效值,则以输出空值开始。
with test(assets) as
( values (array ['£472.96k', '£142.6m', '£500', '-£3.38m' , 'xxx'] ) )
, exp(re) as
( values ('^(\+|-)?([0-9]*\.?[0-9]*)(m|k)?$'))
select orig_asset
, case when assets ~ re
then case when asset_mag = 'k'
then asset_val * 1000::float
when asset_mag = 'm'
then asset_val * 1000000::float
else asset_val
end
else null
end asset_value
from (select orig_asset,assets, re
, regexp_replace (assets, re,'\1\2')::float asset_val
, regexp_replace (assets, re,'\3') asset_mag
from exp cross join
( select assets orig_asset
, replace(assets,'£','') assets
from ( select unnest(assets) assets from test) a
) b
) c;
最后,您可以将整个查询包装到一个返回表的 SQL 函数中。可以像任何表一样使用其结果是查询。有关每个示例,请参见fiddle here
推荐阅读
- python - 在 Python 3.6 中实例化自定义类后内部类对象未重置
- java - 助记符适用于 MenuBar 但不适用于 MenuItems
- linux - 将 ZFS 快照应用到非 ZFS FS
- proxy - Kubernetes 和 Prometheus 不与 Grafana 一起工作
- java - 如何通过拖动鼠标/手指来移动身体/演员?
- android - 按值的日期属性对 Hashmap 键进行排序
- python - IndexError: 元组索引超出范围 --- Python
- vb.net - 根据数据集值在 windows 窗体上创建阈值
- html - Bootstrap 4 Grid - 行的长度不同
- python - 运行 def __init__(self) 函数后,如何在类对象中添加数据?