Python Pandas十进制标记欧盟到美国

时间:2013-07-08 16:14:24

标签: pandas decimal

我将关于欧盟的邮件红色转换为美国小数点转换,这些帮助很多,但我还是觉得需要专家的帮助。我的数据来自ERP系统,其数字格式如下" 1' 000' 000,32"而且我只想简单地转换成" 1000000.32"在熊猫进一步加工。

我从欧盟开始获取美国格式的实际解决方案如下:

... 
 # read_csv and merge, clean .. different CSV files
 # result = merge (some_DataFrame_EU_format, ...)
...
result.to_csv(path, sep';')
result = read_csv(path, sep';', converters={'column_name': lambda x: float(x.replace   ('.','').replace(',','.'))})
....
result.to_csv(path, sep';')

我觉得这是改变''的一种缓慢的方法。用'。'因为read_csv和to_csv(和磁盘..)所以愿意直接在DataFrame上尝试.replace方法来节省一些处理时间。

我最初的尝试是类似下面的内容(我在论坛上的其他地方红了......):

result['column_name'] = result['column_name'].replace( '.', '')
result['column_name'] = result['column_name'].replace( ',', '.')
result['column_name'] =  result['column_name'].astype(float)

哪个没有效果,导致了浮动的无效文字'错误'

我很感动:

for i in range (0, len(result)):
    result.ix[i,'column_name'] = result.ix[i,'column_name'].replace( '.', '')
    result.ix[i,'column_name'] = result.ix[i,'column_name'].replace( ',', '.')
result['column_name'] =  result['column_name'].astype(float)

上面的工作......虽然有些意外,它看起来比read_csv / converter解决方案慢了约3倍。使用以下内容有所帮助:

    for i in range (0, len(result)):
    result.ix[i,'column_name'] = result.ix[i,'column_name'].replace( '.', '').replace( ',', '.')
    result['column_name'] =  result['column_name'].astype(float)

我重写了精美的手册..并且知道read_csv已经过优化..但是并没有真正期望红色/写/读/写cicle比for循环快三倍!!

你认为在这方面做更多工作可能值得吗?有什么建议吗?或者继续使用重复的写/读/写方法更好?

我的文件大约是30k行x 150列,读/写/读(转换)/写大约需要18秒,.ix for大于52秒,第一种循环(32和分组.replace) )。

您将DataFrames从欧盟格式转换为美国格式有何经验?一些建议的改进方法?怎么样'映射'或者' locale' ?他们可能会更快吗?

非常感谢Fabio。

P.S。我意识到自己很啰嗦'并没有想到' pythonic'对不起抱歉..我还在学习......: - )

3 个答案:

答案 0 :(得分:2)

实际上read_csv中有一个千位和十进制参数 (见pandas documentation read_csv 但不幸的是,两者还没有合作(见问题:github issue

答案 1 :(得分:1)

非常感谢你给我的建议和帮助,安迪和杰夫!你帮了很多忙: - )

我首先带着编辑回到原始数据。在其中一些我看到系统可能应用了某种自动转换,所以我新下载了与'未转换'选项相同的数据集,并避免使用例如Excel或其他程序来打开/保存文件。我只使用文本编辑器。在这一点上,我使read_csv更轻,没有转换器,并按照Jeff的建议对替换进行分组。

真实情况比提供的示例稍长,包括一些剥离(空格),列del,字符串concat,重命名/替换....小数标记替换为三列:USD Sales,Qty,USD_EUR汇率。根据它们计算欧元销售额和欧元单价。在初始文件中,由于其他原因,我们还有一个' - ',在汇率固定之前(“ - ”,“”)。结果是:

result = pd.read_csv(path, sep=';', thousands = '.')
col = [ 'qty', 'sales', 'rate']
result[col] = result[col].apply(lambda x: x.str.replace(".","").str.replace(",","."))
result['sales_localcurrency'] = abs(result['sales'].astype(float) / result['rate'].astype(float))
result['sales_localcurrency_unit'] = result['sales_localcurrency'] / result['qty'].astype(float)
result.to_csv(path, sep=';')

30'000 x 150 DataFrame在不到15秒的时间内处理:-) :-)包括我在这里没详述的所有其他东西(剥离,del,concat,..)。所有读/写/读/写都已从read_csv中跳过'转换器'的代码中删除。

感谢您的帮助:-)!

再见。再见。法比奥。

        -

答案 2 :(得分:0)

使用您指定的值创建一个框架并写入csv

In [2]: df = DataFrame("100'100,32",index=range(30000),columns=range(150))

In [3]: df.iloc[0:5,0:5]
Out[3]: 
            0           1           2           3           4
0  100'100,32  100'100,32  100'100,32  100'100,32  100'100,32
1  100'100,32  100'100,32  100'100,32  100'100,32  100'100,32
2  100'100,32  100'100,32  100'100,32  100'100,32  100'100,32
3  100'100,32  100'100,32  100'100,32  100'100,32  100'100,32
4  100'100,32  100'100,32  100'100,32  100'100,32  100'100,32

In [4]: df.to_csv('test.csv')

读入,没有转换器

In [5]: df = read_csv('../test.csv',index_col=0)

In [6]: %timeit read_csv('../test.csv',index_col=0)
1 loops, best of 3: 1e+03 ms per loop

In [7]: df
Out[7]: 
<class 'pandas.core.frame.DataFrame'>
Int64Index: 30000 entries, 0 to 29999
Columns: 150 entries, 0 to 149
dtypes: object(150)

In [8]: %timeit read_csv('../test.csv',index_col=0)
1 loops, best of 3: 1e+03 ms per loop

逐列替换字符串。如果您在这里,您只能指定某些列 希望,通过df[[ list of columns ]].apply(.....)

In [9]: df.apply(lambda x: x.str.replace("'","").str.replace(",",".")).astype(float)
Out[9]: 
<class 'pandas.core.frame.DataFrame'>
Int64Index: 30000 entries, 0 to 29999
Columns: 150 entries, 0 to 149
dtypes: float64(150)

In [10]: %timeit df.apply(lambda x: x.str.replace("'","").str.replace(",",".")).astype(float)
1 loops, best of 3: 4.77 s per loop

总时间低于6s

仅供参考,有一个thousands单独选项,但不是decimal一个....嗯这会快得多......