美文网首页Pandas技巧
Python Pandas——Read_csv详解

Python Pandas——Read_csv详解

作者: Kaspar433 | 来源:发表于2020-03-22 17:13 被阅读0次

    Python Pandas——Read_csv详解

    目前最常用的数据保存格式可能就是CSV格式了,数据分析第一步就是获取数据,怎样读取数据至关重要。

    本文将以pandas read_csv方法为例,详细介绍read_csv数据读取方法。再数据读取时进行数据预处理,这样不仅可以加快读取速度,同时为后期数据清洗及分析打下基础。

    导入必要的库

    import pandas as pd
    import numpy as np
    from pandas.api.types import CategoricalDtype
    from io import StringIO
    

    Specifying Column Data Types

    可以指定整个DataFrame或各个列的数据类型:

    data = pd.read_csv('diamonds.csv',dtype=object)
    data.head()
    
    out:
    carat   cut color   clarity depth   table   price   x   y   z
    0   0.23    Ideal   E   SI2 61.5    55  326 3.95    3.98    2.43
    1   0.21    Premium E   SI1 59.8    61  326 3.89    3.84    2.31
    2   0.23    Good    E   VS1 56.9    65  327 4.05    4.07    2.31
    3   0.29    Premium I   VS2 62.4    58  334 4.2 4.23    2.63
    4   0.31    Good    J   SI2 63.3    58  335 4.34    4.35    2.75
    
    data.dtypes
    
    out:
    carat      object
    cut        object
    color      object
    clarity    object
    depth      object
    table      object
    price      object
    x          object
    y          object
    z          object
    dtype: object
    
    data = pd.read_csv('diamonds.csv',dtype={'carat': np.float64,'depth': np.float64,'table':np.float64})
    data.dtypes
    out:
    carat      float64
    cut         object
    color       object
    clarity     object
    depth      float64
    table      float64
    price        int64
    x          float64
    y          float64
    z          float64
    dtype: object
    

    pandas提供了多种方法来确保列仅包含一个dtype。例如,可以使用read_csv()的converters参数:

    data = pd.read_csv('diamonds.csv',converters={'carat':str})
    data.dtypes
    out:
    carat       object
    cut         object
    color       object
    clarity     object
    depth      float64
    table      float64
    price        int64
    x          float64
    y          float64
    z          float64
    dtype: object
    
    data.carat.apply(type).value_counts()
    
    out:
    <class 'str'>    53940
    Name: carat, dtype: int64
    

    或者,可以在读取数据后使用to_numeric()函数强进行类型转换。

    data.carat = pd.to_numeric(data['carat'],errors='coerce')
    data.carat.apply(type).value_counts()
    
    out:
    <class 'float'>    53940
    Name: carat, dtype: int64
    

    Specigying Categorical Dtype¶

    可以通过指定dtype ='category'或dtype = CategoricalDtype(类别,有序)直接解析类别列。

    data = pd.read_csv('diamonds.csv',dtype='category')
    data.dtypes
    
    out:
    carat      category
    cut        category
    color      category
    clarity    category
    depth      category
    table      category
    price      category
    x          category
    y          category
    z          category
    dtype: object
    

    可以使用dict指定将某列为Category类型:

    data = pd.read_csv('diamonds.csv',dtype={'cut':'category'})
    data.dtypes
    
    out:
    carat       float64
    cut        category
    color        object
    clarity      object
    depth       float64
    table       float64
    price         int64
    x           float64
    y           float64
    z           float64
    dtype: object
    
    data.cut.value_counts()
    
    out:
    Ideal        21551
    Premium      13791
    Very Good    12082
    Good          4906
    Fair          1610
    Name: cut, dtype: int64
    

    指定dtype ='category'将导致无序分类,其类别是数据中观察到的唯一值。

    要更好地控制类别和顺序,可以创建CategoricalDtype,然后将其传递给该列的dtype。

    from pandas.api.types import CategoricalDtype
    dtype = CategoricalDtype(['Ideal','Premium','Very Good','Good','Fair'],ordered=True)
    data = pd.read_csv('diamonds.csv',dtype={'cut':dtype})
    data.dtypes
    
    out:
    carat       float64
    cut        category
    color        object
    clarity      object
    depth       float64
    table       float64
    price         int64
    x           float64
    y           float64
    z           float64
    dtype: object
    

    使用dtype = CategoricalDtype时,dtype.categories之外的“意外”值将被视为缺失值。

    from pandas.api.types import CategoricalDtype
    dtype = CategoricalDtype(['Ideal','Premium','Very Good','Good'],ordered=True)
    data = pd.read_csv('diamonds.csv',dtype={'cut':dtype})
    data[data.cut.isnull()].head()
    
    out:
        carat   cut color   clarity depth   table   price   x   y   z
    8   0.22    NaN E   VS2 65.1    61.0    337 3.87    3.78    2.49
    91  0.86    NaN E   SI2 55.1    69.0    2757    6.45    6.33    3.52
    97  0.96    NaN F   SI2 66.3    62.0    2759    6.27    5.95    4.07
    123 0.70    NaN F   VS2 64.5    57.0    2762    5.57    5.53    3.58
    124 0.70    NaN F   VS2 65.3    55.0    2762    5.63    5.58    3.66
    

    Naming and Using Columns

    Handling Column names

    文件可能包含标题行,也可能没有标题行。 pandas假定第一行应用作列名:

    from io import StringIO
    data = ('a,b,c\n'
            '1,2,3\n'
            '4,5,6\n'
            '7,8,9')
    pd.read_csv(StringIO(data))
    
    out:
        a   b   c
    0   1   2   3
    1   4   5   6
    2   7   8   9
    

    通过指定name与header,可以重命名列以及是否丢弃标题行:

    pd.read_csv(StringIO(data),names=['foo','bar','baz'],header=0)
    
    out:
        foo bar baz
    0   1   2   3
    1   4   5   6
    2   7   8   9
    
    pd.read_csv(StringIO(data),names=['foo','bar','baz'],header=None)
    
    out:
        foo bar baz
    0   a   b   c
    1   1   2   3
    2   4   5   6
    3   7   8   9
    

    如果标题不在第一行中,则将行号传递给标题,将跳过header前面的行:

    data = ('skip this skip it\n'
            'a,b,c\n'
            '1,2,3\n'
            '4,5,6\n'
            '7,8,9')
    pd.read_csv(StringIO(data),header=1)
    
    out:
        a   b   c
    0   1   2   3
    1   4   5   6
    2   7   8   9
    Duplicate Names Parsing
    

    如果文件或标题包含重复的名称,默认情况下,pandas会将它们区分开,以防止覆盖数据.

    data = ('a,b,a\n'
           '0,1,2\n'
           '3,4,5')
    print(data)
    
    out:
    a,b,a
    0,1,2
    3,4,5
    
    pd.read_csv(StringIO(data))
    
    out:
        a   b   a.1
    0   0   1   2
    1   3   4   5
    Filtering Columns(usecols)
    

    usecols参数允许您使用列名,位置号或可调用的方法选择文件中列的任何子集.

    data = 'a,b,c,d\n1,2,3,foo\n4,5,6,bar\n7,8,9,baz'
    pd.read_csv(StringIO(data))
    
    out:
        a   b   c   d
    0   1   2   3   foo
    1   4   5   6   bar
    2   7   8   9   baz
    
    pd.read_csv(StringIO(data),usecols=['b','d'])
    
    out:
        b   d
    0   2   foo
    1   5   bar
    2   8   baz
    
    pd.read_csv(StringIO(data),usecols=[0,1,3])
    
    out:
        a   b   d
    0   1   2   foo
    1   4   5   bar
    2   7   8   baz
    
    pd.read_csv(StringIO(data),usecols=lambda x: x.upper() in ['A','C'])
    
    out:
        a   c
    0   1   3
    1   4   6
    2   7   9
    
    pd.read_csv(StringIO(data),usecols=lambda x: x.upper() not in ['A','C'])
    
    out:
        b   d
    0   2   foo
    1   5   bar
    2   8   baz
    

    Comments and Empty Lines

    Ignoring Line Comments And Empty Lines

    如果指定了comment参数,则将忽略注释行。 默认情况下,空行也将被忽略。

    data = ('\n'
            'a,b,c\n'
            ' \n'
            '# commented line\n'
            '1,2,3\n'
            '\n'
            '4,5,6')
    print(data)
    
    out:
    
    a,b,c
     
    # commented line
    1,2,3
    
    4,5,6
    
    pd.read_csv(StringIO(data),comment='#')
    
    out:
        a   b   c
    0   1   2   3
    1   4   5   6
    

    如果skip_blank_lines = False,则read_csv将不会忽略空行:

    pd.read_csv(StringIO(data),comment='#',skip_blank_lines=False)
    
    out:
    a   b   c
    NaN NaN
    1   2   3
    NaN NaN NaN
    4   5   6
    

    警告:被忽略的行的存在可能会导致涉及行号的歧义; 参数标题使用行号(忽略注释/空行),而行首使用行号(包括注释/空行).

    data = ('#comment\n'
            'a,b,c\n'
            'A,B,C\n'
            '1,2,3')
    pd.read_csv(StringIO(data),comment='#',header=1)
    
    out:
        A   B   C
    0   1   2   3
    
    pd.read_csv(StringIO(data),comment='#',skiprows=2)
        A   B   C
    0   1   2   3
    

    如果同时指定了skiprows和header,则header将相对于skiprows的末尾。 例如:

    data = ('# empty\n'
            '# second empty line\n'
            '# third emptyline\n'
            'X,Y,Z\n'
            '1,2,3\n'
            'A,B,C\n'
            '1,2.,4.\n'
            '5.,NaN,10.0\n')
    print(data)
    
    out:
    # empty
    # second empty line
    # third emptyline
    X,Y,Z
    1,2,3
    A,B,C
    1,2.,4.
    5.,NaN,10.0
    
    pd.read_csv(StringIO(data),comment='#',skiprows=4,header=1)
    
    out:
        A   B   C
    0   1.0 2.0 4.0
    1   5.0 NaN 10.0
    
    pd.read_csv(StringIO(data),skiprows=4,header=1)
    
    out:
        A   B   C
    0   1.0 2.0 4.0
    1   5.0 NaN 10.0
    

    Comments

    tmp = ('ID,level,category\n'
           'Patient1,123000,x # really unpleasant\n'
           'Patient2,23000,y # wouldn\'t take his medicine\n'
           'Patient3,1234018,z # awesome')
    pd.read_csv(StringIO(tmp))
    
    out:
    ID  level   category
    0   Patient1    123000  x # really unpleasant
    1   Patient2    23000   y # wouldn't take his medicine
    2   Patient3    1234018 z # awesome
    
    pd.read_csv(StringIO(tmp),comment='#')
    
    out:
        ID  level   category
    0   Patient1    123000  x
    1   Patient2    23000   y
    2   Patient3    1234018 z
    

    Index Columns And Trailing Delimiters

    data = ('a,b,c\n'
            '4,apple,bat,5.7\n'
            '8,orange,cow,10')
    pd.read_csv(StringIO(data))
    
    out:
        a   b   c
    4   apple   bat 5.7
    8   orange  cow 10.0
    
    pd.read_csv(StringIO(data),index_col=0)
    
    out:
        a   b   c
    4   apple   bat 5.7
    8   orange  cow 10.0
    
    data = ('a,b,c\n'
            '4,apple,bat\n'
            '8,orange,cow')
    pd.read_csv(StringIO(data))
    
    out:
        a   b   c
    0   4   apple   bat
    1   8   orange  cow
    
    pd.read_csv(StringIO(data),index_col=0)
    
    out:
        b   c
    a       
    4   apple   bat
    8   orange  cow
    
    pd.read_csv(StringIO(data),usecols=['b','c'])
    
    out:
        b   c
    0   apple   bat
    1   orange  cow
    
    pd.read_csv(StringIO(data),usecols=['b','c'],index_col=0)
    
    out:
        c
    b   
    apple   bat
    orange  cow
    

    Date Handling

    Specifying Date Columns

    为了更好地使用日期时间数据,read_csv()使用关键字参数parse_dates和date_parser允许用户指定列的日期/时间格式,将string转换为日期时间对象。

    foo = ('date,A,B,C\n'
          '2009-01-01,a,1,2\n'
          '2009-01-02,b,3,4\n'
          '2009-01-03,c,4,5\n')
    pd.read_csv(StringIO(foo),index_col=0,parse_dates=True)
    
    out:
        A   B   C
    date            
    2009-01-01  a   1   2
    2009-01-02  b   3   4
    2009-01-03  c   4   5
    
    pd.read_csv(StringIO(foo),index_col=0,parse_dates=True).index
    DatetimeIndex(['2009-01-01', '2009-01-02', '2009-01-03'], dtype='datetime64[ns]', name='date', freq=None)
    

    通常,我们可能希望分别存储日期和时间数据,或分别存储各种日期字段。 parse_dates关键字可用于指定列的组合,以从中解析日期和/或时间。 您可以指定要parse_dates的列或嵌套列表,结果日期列将被添加到输出的前面(以便不影响现有的列顺序),新的列名为各列Name的连接。

    tmp = ('KORD,19990127, 19:00:00, 18:56:00, 0.8100\n'
           'KORD,19990127, 20:00:00, 19:56:00, 0.0100\n'
           'KORD,19990127, 21:00:00, 20:56:00, -0.5900\n'
           'KORD,19990127, 21:00:00, 21:18:00, -0.9900\n'
           'KORD,19990127, 22:00:00, 21:56:00, -0.5900\n'
           'KORD,19990127, 23:00:00, 22:56:00, -0.5900')
    pd.read_csv(StringIO(tmp),header=None,parse_dates=[[1,2],[1,3]])
    
    out:
        1_2 1_3 0   4
    0   1999-01-27 19:00:00 1999-01-27 18:56:00 KORD    0.81
    1   1999-01-27 20:00:00 1999-01-27 19:56:00 KORD    0.01
    2   1999-01-27 21:00:00 1999-01-27 20:56:00 KORD    -0.59
    3   1999-01-27 21:00:00 1999-01-27 21:18:00 KORD    -0.99
    4   1999-01-27 22:00:00 1999-01-27 21:56:00 KORD    -0.59
    5   1999-01-27 23:00:00 1999-01-27 22:56:00 KORD    -0.59
    

    默认情况下,解析器会删除组件日期列,可以选择通过keep_date_col关键字保留它们:

    pd.read_csv(StringIO(tmp),header=None,parse_dates=[[1,2],[1,3]],keep_date_col=True)
    
    out:
        1_2 1_3 0   1   2   3   4
    0   1999-01-27 19:00:00 1999-01-27 18:56:00 KORD    19990127    19:00:00    18:56:00    0.81
    1   1999-01-27 20:00:00 1999-01-27 19:56:00 KORD    19990127    20:00:00    19:56:00    0.01
    2   1999-01-27 21:00:00 1999-01-27 20:56:00 KORD    19990127    21:00:00    20:56:00    -0.59
    3   1999-01-27 21:00:00 1999-01-27 21:18:00 KORD    19990127    21:00:00    21:18:00    -0.99
    4   1999-01-27 22:00:00 1999-01-27 21:56:00 KORD    19990127    22:00:00    21:56:00    -0.59
    5   1999-01-27 23:00:00 1999-01-27 22:56:00 KORD    19990127    23:00:00    22:56:00    -0.59
    

    请注意,如果您希望将多个列合并为一个日期列,则必须使用嵌套列表。 换句话说,parse_dates = [1,2]表示第二和第三列应分别解析为单独的日期列,而parse_dates = [[1,2]]意味着应将这两列解析为单个列。

    还可以使用字典来指定自定义名称列:

    date_spec = {'nominal':[1,2],'actual':[1,3]}
    pd.read_csv(StringIO(tmp),header=None,parse_dates=date_spec)
    
    out:
        nominal actual  0   4
    0   1999-01-27 19:00:00 1999-01-27 18:56:00 KORD    0.81
    1   1999-01-27 20:00:00 1999-01-27 19:56:00 KORD    0.01
    2   1999-01-27 21:00:00 1999-01-27 20:56:00 KORD    -0.59
    3   1999-01-27 21:00:00 1999-01-27 21:18:00 KORD    -0.99
    4   1999-01-27 22:00:00 1999-01-27 21:56:00 KORD    -0.59
    5   1999-01-27 23:00:00 1999-01-27 22:56:00 KORD    -0.59
    

    重要的是要记住,如果要将多个文本列解析为单个日期列,则在数据前添加一个新列。

    index_col参数基于这组新列而不是原始数据列:

    pd.read_csv(StringIO(tmp),header=None,parse_dates=date_spec,index_col=0)
    
    out:
        actual  0   4
    nominal         
    1999-01-27 19:00:00 1999-01-27 18:56:00 KORD    0.81
    1999-01-27 20:00:00 1999-01-27 19:56:00 KORD    0.01
    1999-01-27 21:00:00 1999-01-27 20:56:00 KORD    -0.59
    1999-01-27 21:00:00 1999-01-27 21:18:00 KORD    -0.99
    1999-01-27 22:00:00 1999-01-27 21:56:00 KORD    -0.59
    1999-01-27 23:00:00 1999-01-27 22:56:00 KORD    -0.59
    

    注意:如果列或索引包含不可解析的日期,则整个列或索引将作为对象数据类型原样返回。 对于非标准日期时间解析,请在pd.read_csv之后使用to_datetime()。

    注意:read_csv具有用于解析iso8601格式的日期时间字符串的fast_path,例如“ 2000-01-01T00:01:02 + 00:00”和类似的变体。 如果可以安排数据以这种格式存储日期时间,则加载时间将明显缩短,约20倍。

    Date Parsing Functions

    最后,解析器允许您指定自定义date_parser函数,以充分利用日期解析API的灵活性:

    pd.read_csv(StringIO(tmp),header=None,parse_dates=date_spec,
                date_parser=pd.io.date_converters.parse_date_time)
    
    out:
        nominal actual  0   4
    0   1999-01-27 19:00:00 1999-01-27 18:56:00 KORD    0.81
    1   1999-01-27 20:00:00 1999-01-27 19:56:00 KORD    0.01
    2   1999-01-27 21:00:00 1999-01-27 20:56:00 KORD    -0.59
    3   1999-01-27 21:00:00 1999-01-27 21:18:00 KORD    -0.99
    4   1999-01-27 22:00:00 1999-01-27 21:56:00 KORD    -0.59
    5   1999-01-27 23:00:00 1999-01-27 22:56:00 KORD    -0.59
    

    Parsing A Csv with Mixed Timezones

    Pandas不能原生表示具有混合时区的列或索引。 如果CSV文件包含带有时区混合的列,则默认结果将是带有字符串的object-dtype列,即使包含parse_dates。

    content = ('a\n'
            '2000-01-01T00:00:00+05:00\n'
            '2000-01-01T00:00:00+06:00\n')
    pd.read_csv(StringIO(content),parse_dates=['a'])
    
    out:
        a
    0   2000-01-01 00:00:00+05:00
    1   2000-01-01 00:00:00+06:00
    

    要将混合时区值解析为datetime列,请将部分应用的to_datetime()传递给utc = True作为date_parser。

    pd.read_csv(StringIO(content),parse_dates=['a'],
               date_parser=lambda col:pd.to_datetime(col,utc=True))
    
    out:
        a
    0   1999-12-31 19:00:00+00:00
    1   1999-12-31 18:00:00+00:00
    ​

    相关文章

      网友评论

        本文标题:Python Pandas——Read_csv详解

        本文链接:https://www.haomeiwen.com/subject/wgyvyhtx.html