【问题标题】:Importing financial data into Python Pandas using read_csv使用 read_csv 将财务数据导入 Python Pandas
【发布时间】:2015-02-16 13:00:12
【问题描述】:

我有一个具有以下结构的 .csv:

date_begin,date_end,name,name_code,active_accounts,transaction_amount,transaction_count
1/1/2008,1/31/2008,Name_1,1001,"123,456","$7,890,123.45","67,890"
2/1/2008,2/29/2008,Name_1,1001,"43,210","$987,654.32","109,876"
3/1/2008,3/31/2008,Name_1,1001,"485,079","$1,265,789,433.98","777,888"
...
12/1/2008,12/31/2008,Name_1,1001,"87,543","$432,098,987","87,987"
1/1/2008,1/31/2008,Name_2,1002,"268,456","$890,123.45","97,890"
2/1/2008,2/29/2008,Name_2,1002,"53,210","$987,654.32","109,876"
...
etc

我正在尝试使用以下代码将它们读入熊猫数据框:

import pandas as pd

data = pd.read_csv('my_awesome_csv.csv'),parse_dates=[[0,1]],
                   infer_datetime_format=True)

除了我想控制每列中的数据类型之外,这很好用。当我在解释器中运行以下代码时,我发现引号中的数字不会被识别为数字,无论是美元还是其他。

In [10]: data.dtypes
Out[10]: 
date_begin_date_end       object
name                      object
name_code                  int64
active_accounts           object  # Problem, I want this to be a number
transaction_amount        object  # Ditto, I want this to be a number (it's a dollar amount)
transaction_count         object  # Still a number!
dtype: object

我已经在Pandas csv documentation 中进行了一些窥探,但还没有找到我正在寻找的关于在 csv 中将它们保存为带有逗号和美元符号的字符串时声明类型的内容。我的最终目标是能够对这些列中的值进行一些算术运算。

有什么想法吗?

【问题讨论】:

    标签: python csv pandas import


    【解决方案1】:

    您可以在调用后使用 vectorized string methods 解析这些列 read_csv:

    import pandas as pd
    import decimal
    D = decimal.Decimal
    
    data = pd.read_csv('data', parse_dates=[[0,1]], infer_datetime_format=True)
    
    for col in ('active_accounts', 'transaction_count'):
        data[col] = data[col].str.replace(r',', '').astype(int)
    
    data['transaction_amount'] = (data['transaction_amount']
                                  .str.replace(r'[^-+\d.]', '').astype(D))
    
    
    print(data.dtypes)
    # date_begin_date_end    object
    # name                   object
    # name_code               int64
    # active_accounts         int64
    # transaction_amount     object
    # transaction_count       int64
    # dtype: object
    
    print(data)
    

    产量

        date_begin_date_end    name  name_code  active_accounts  \
    0    1/1/2008 1/31/2008  Name_1       1001           123456   
    1    2/1/2008 2/29/2008  Name_1       1001            43210   
    2    3/1/2008 3/31/2008  Name_1       1001           485079   
    3  12/1/2008 12/31/2008  Name_1       1001            87543   
    4    1/1/2008 1/31/2008  Name_2       1002           268456   
    5    2/1/2008 2/29/2008  Name_2       1002            53210   
    
      transaction_amount  transaction_count  
    0         7890123.45              67890  
    1          987654.32             109876  
    2      1265789433.98             777888  
    3          432098987              87987  
    4          890123.45              97890  
    5          987654.32             109876  
    

    附言。 read_csv 确实有 converters parameter 您可以使用它提供一个函数来解析有问题的列。这些 每个字符串调用一次函数。如果你有很多行,那可能需要很多 Python 函数 来电。使用矢量化字符串方法处理列,如上所示 应该快得多。

    import pandas as pd
    import re
    import decimal
    D = decimal.Decimal
    
    def make_parser(cls):
        def parse_commas(text):
            return cls(re.sub(r'[^-+\d.]', '', text))
        return parse_commas
    
    to_int = make_parser(int)
    to_decimal = make_parser(D)
    
    data = pd.read_csv('data', parse_dates=[[0,1]], infer_datetime_format=True
                       , converters={4: to_int, 5: to_decimal, 6: to_int})
    
    print(data)
    

    产量

        date_begin_date_end    name  name_code  active_accounts  \
    0    1/1/2008 1/31/2008  Name_1       1001           123456   
    1    2/1/2008 2/29/2008  Name_1       1001            43210   
    2    3/1/2008 3/31/2008  Name_1       1001           485079   
    3  12/1/2008 12/31/2008  Name_1       1001            87543   
    4    1/1/2008 1/31/2008  Name_2       1002           268456   
    5    2/1/2008 2/29/2008  Name_2       1002            53210   
    
      transaction_amount  transaction_count  
    0         7890123.45              67890  
    1          987654.32             109876  
    2      1265789433.98             777888  
    3          432098987              87987  
    4          890123.45              97890  
    5          987654.32             109876  
    

    transaction_amount 列中的值为十进制。小数:

    In [64]: data.loc[0, 'transaction_amount']
    Out[64]: Decimal('7890123.45')
    

    【讨论】:

    • 感谢您,这似乎是一个优雅而快速的解决方案。我使用 SAS 已经有一段时间了,我习惯于在导入每一列时声明数据的格式,例如“dollar20.2”。这样我就保留了单位是美元的事实。我希望 pandas 除了 float64、int64 等之外还可以内置类似的东西。
    • Pandas 没有货币类型(至少目前还没有)。在 Python 中,表示货币的常用方法是使用decimal 模块或third-party module like python-money。在 pandas DataFrame 中使用这些的缺点是数值计算将不再使用本机 NumPy dtypes,因此会慢得多。因此,如果准确性是您的主要优先事项,则将值转换为 decimal.Decimals(或等效的 python-money 类的实例)。但如果您的首要任务是速度,请使用浮点数。
    • 我已经修改了上面的converters 代码,以展示如何将transaction_amount 列转换为decimal.Decimals。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-06
    • 1970-01-01
    • 2020-04-28
    • 2013-10-27
    • 1970-01-01
    • 2016-09-30
    • 2016-04-20
    相关资源
    最近更新 更多