关于python:更改pandas中列的数据类型

Change data type of columns in Pandas

我想将一个表(表示为列表列表)转换为熊猫数据帧。作为一个非常简单的例子:

1
2
a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0']]
df = pd.DataFrame(a)

将列转换为适当的类型的最佳方法是什么,在这种情况下,将列2和3转换为float?转换为数据帧时是否有指定类型的方法?还是先创建数据帧,然后循环遍历列以更改每列的类型更好?理想情况下,我希望以动态方式执行此操作,因为可能有数百个列,我不想确切地指定哪些列属于哪种类型。我能保证的就是每列都包含相同类型的值。


您有三个转换熊猫类型的主要选项:好的。

  • to_numeric()—提供安全地将非数字类型(如字符串)转换为适当的数字类型的功能。(另见to_datetime()to_timedelta())好的。

  • astype()—将(几乎)任何类型转换为(几乎)任何其他类型(即使这样做不一定明智)。还允许您转换为类别类型(非常有用)。好的。

  • infer_objects()—一种实用方法,在可能的情况下,将包含python对象的对象列转换为pandas类型。好的。

  • 请继续阅读,了解这些方法的更详细解释和用法。好的。1。to_numeric()

    将数据帧的一列或多列转换为数值的最佳方法是使用pandas.to_numeric()。好的。

    此函数将尝试根据需要将非数字对象(如字符串)更改为整数或浮点数。好的。基本用法

    to_numeric()的输入是一个数据帧的序列或单列。好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    >>> s = pd.Series(["8", 6,"7.5", 3,"0.9"]) # mixed string and numeric values
    >>> s
    0      8
    1      6
    2    7.5
    3      3
    4    0.9
    dtype: object

    >>> pd.to_numeric(s) # convert everything to float values
    0    8.0
    1    6.0
    2    7.5
    3    3.0
    4    0.9
    dtype: float64

    如您所见,将返回一个新的序列。请记住将此输出分配给变量或列名以继续使用它:好的。

    1
    2
    3
    4
    5
    # convert Series
    my_series = pd.to_numeric(my_series)

    # convert column"a" of a DataFrame
    df["a"] = pd.to_numeric(df["a"])

    您还可以使用它通过apply()方法转换数据帧的多列:好的。

    1
    2
    3
    4
    5
    # convert all columns of DataFrame
    df = df.apply(pd.to_numeric) # convert all columns of DataFrame

    # convert just columns"a" and"b"
    df[["a","b"]] = df[["a","b"]].apply(pd.to_numeric)

    只要你的值都能被转换,这可能就是你所需要的。好的。错误处理

    但是如果一些值不能转换成数字类型呢?好的。

    to_numeric()还接受一个errors关键字参数,该参数允许您强制非数字值为NaN,或者只忽略包含这些值的列。好的。

    下面是一个使用一系列字符串s的示例,该字符串具有对象数据类型:好的。

    1
    2
    3
    4
    5
    6
    7
    8
    >>> s = pd.Series(['1', '2', '4.7', 'pandas', '10'])
    >>> s
    0         1
    1         2
    2       4.7
    3    pandas
    4        10
    dtype: object

    如果无法转换值,则默认行为是提升。在这种情况下,它无法处理字符串"pandas":好的。

    1
    2
    >>> pd.to_numeric(s) # or pd.to_numeric(s, errors='raise')
    ValueError: Unable to parse string

    我们可能希望"pandas"被视为丢失/错误的数值,而不是失败。我们可以使用errors关键字参数将无效值强制为NaN,如下所示:好的。

    1
    2
    3
    4
    5
    6
    7
    >>> pd.to_numeric(s, errors='coerce')
    0     1.0
    1     2.0
    2     4.7
    3     NaN
    4    10.0
    dtype: float64

    errors的第三个选项是,如果遇到无效值,则忽略该操作:好的。

    1
    2
    >>> pd.to_numeric(s, errors='ignore')
    # the original Series is returned untouched

    最后一个选项在您希望转换整个数据帧时特别有用,但不知道哪一列可以可靠地转换为数字类型。在这种情况下,只需写:好的。

    1
    df.apply(pd.to_numeric, errors='ignore')

    该函数将应用于数据帧的每一列。可以转换为数字类型的列将被转换,而不能转换的列(例如,它们包含非数字字符串或日期)将被单独保留。好的。向下转型

    默认情况下,使用to_numeric()的转换将为您提供int64float64数据类型(或平台本身的任何整数宽度)。好的。

    这通常是您想要的,但是如果您想要保存一些内存并使用更紧凑的数据类型,比如float32int8,该怎么办?好的。

    to_numeric()提供向下强制转换为"integer"、"signed"、"unsigned"、"float"的选项。下面是一个简单的整数型系列s的示例:好的。

    1
    2
    3
    4
    5
    6
    >>> s = pd.Series([1, 2, -7])
    >>> s
    0    1
    1    2
    2   -7
    dtype: int64

    向下转换为"integer"时使用可以保存值的最小可能整数:好的。

    1
    2
    3
    4
    5
    >>> pd.to_numeric(s, downcast='integer')
    0    1
    1    2
    2   -7
    dtype: int8

    向下转换为"float"类似地选择一个小于正常的浮动类型:好的。

    1
    2
    3
    4
    5
    >>> pd.to_numeric(s, downcast='float')
    0    1.0
    1    2.0
    2   -7.0
    dtype: float32

    2。astype()

    astype()方法使您能够明确地了解希望数据帧或序列具有的数据类型。它的用途非常广泛,你可以尝试从一种类型到另一种类型。好的。基本用法

    只需选择一个类型:您可以使用numpy数据类型(例如np.int16)、一些python类型(例如bool)或pandas特定类型(例如categorial数据类型)。好的。

    调用要转换的对象的方法,astype()将尝试为您转换该方法:好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # convert all DataFrame columns to the int64 dtype
    df = df.astype(int)

    # convert column"a" to int64 dtype and"b" to complex type
    df = df.astype({"a": int,"b": complex})

    # convert Series to float16 type
    s = s.astype(np.float16)

    # convert Series to Python strings
    s = s.astype(str)

    # convert Series to categorical type - see docs for more details
    s = s.astype('category')

    注意,我说的是"尝试"——如果astype()不知道如何转换序列或数据帧中的值,它将引发错误。例如,如果您有一个NaNinf值,那么在尝试将其转换为整数时会得到一个错误。好的。

    从熊猫0.20.0开始,这个误差可以通过传递errors='ignore'来抑制。您的原始对象将原封不动地返回。好的。小心

    astype()很强大,但有时它会"错误"地转换值。例如:好的。

    1
    2
    3
    4
    5
    6
    >>> s = pd.Series([1, 2, -7])
    >>> s
    0    1
    1    2
    2   -7
    dtype: int64

    这些是小整数,那么转换为无符号8位类型以节省内存如何?好的。

    1
    2
    3
    4
    5
    >>> s.astype(np.uint8)
    0      1
    1      2
    2    249
    dtype: uint8

    转换成功了,但是-7被包裹成了249(即28-7)!好的。

    尝试使用pd.to_numeric(s, downcast='unsigned')而不是downcast有助于防止此错误。好的。三。infer_objects()

    panda的0.21.0版引入了方法infer_objects(),用于将具有对象数据类型的数据帧的列转换为更具体的类型(软转换)。好的。

    例如,这里有一个具有两列对象类型的数据框。一个包含实际整数,另一个包含表示整数的字符串:好的。

    1
    2
    3
    4
    5
    >>> df = pd.DataFrame({'a': [7, 1, 5], 'b': ['3','2','1']}, dtype='object')
    >>> df.dtypes
    a    object
    b    object
    dtype: object

    使用infer_objects()可以将列"a"的类型更改为Int64:好的。

    1
    2
    3
    4
    5
    >>> df = df.infer_objects()
    >>> df.dtypes
    a     int64
    b    object
    dtype: object

    列"b"被单独保留,因为它的值是字符串,而不是整数。如果要尝试强制将两列转换为整数类型,可以使用df.astype(int)。好的。好啊。


    这个怎么样?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0']]
    df = pd.DataFrame(a, columns=['one', 'two', 'three'])
    df
    Out[16]:
      one  two three
    0   a  1.2   4.2
    1   b   70  0.03
    2   x    5     0

    df.dtypes
    Out[17]:
    one      object
    two      object
    three    object

    df[['two', 'three']] = df[['two', 'three']].astype(float)

    df.dtypes
    Out[19]:
    one       object
    two      float64
    three    float64


    下面的代码将更改列的数据类型。

    1
    df[['col.name1', 'col.name2'...]] = df[['col.name1', 'col.name2'..]].astype('data_type')

    代替数据类型,你可以给出你的数据类型。你想要什么,比如str,float,int等等。


    这是一个函数,它将数据框和列列表作为参数,并将列中的所有数据强制为数字。

    1
    2
    3
    4
    5
    # df is the DataFrame, and column_list is a list of columns as strings (e.g ["col1","col2","col3"])
    # dependencies: pandas

    def coerce_df_columns_to_numeric(df, column_list):
        df[column_list] = df[column_list].apply(pd.to_numeric, errors='coerce')

    因此,举个例子:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import pandas as pd

    def coerce_df_columns_to_numeric(df, column_list):
        df[column_list] = df[column_list].apply(pd.to_numeric, errors='coerce')

    a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0']]
    df = pd.DataFrame(a, columns=['col1','col2','col3'])

    coerce_df_columns_to_numeric(df, ['col2','col3'])

    如何创建两个数据帧,每个数据帧的列都有不同的数据类型,然后将它们附加在一起?

    1
    2
    d1 = pd.DataFrame(columns=[ 'float_column' ], dtype=float)
    d1 = d1.append(pd.DataFrame(columns=[ 'string_column' ], dtype=str))

    结果

    1
    2
    3
    4
    5
    In[8}:  d1.dtypes
    Out[8]:
    float_column     float64
    string_column     object
    dtype: object

    创建数据帧后,可以在第一列中用浮点变量填充它,在第二列中用字符串(或任何您需要的数据类型)填充它。


    当我只需要指定特定的列,并且希望明确时,我使用了(每个文档位置):

    1
    dataframe = dataframe.astype({'col_name_1':'int','col_name_2':'float64', etc. ...})

    所以,使用原来的问题,但提供列名…

    1
    2
    3
    a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0']]
    df = pd.DataFrame(a, columns=['col_name_1', 'col_name_2', 'col_name_3'])
    df = df.astype({'col_name_2':'float64', 'col_name_3':'float64'})


    我以为我有同样的问题,但实际上我有一个微小的差别,这使得问题更容易解决。对于关注这个问题的其他人来说,值得检查输入列表的格式。在我的例子中,数字最初是浮动的,而不是像问题中那样的字符串:

    1
    a = [['a', 1.2, 4.2], ['b', 70, 0.03], ['x', 5, 0]]

    但是,在创建数据帧之前处理列表太多,我会丢失类型,所有内容都变成字符串。

    通过numpy数组创建数据帧

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    df = pd.DataFrame(np.array(a))

    df
    Out[5]:
       0    1     2
    0  a  1.2   4.2
    1  b   70  0.03
    2  x    5     0

    df[1].dtype
    Out[7]: dtype('O')

    给出与问题中相同的数据帧,其中第1列和第2列中的条目被视为字符串。然而做

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    df = pd.DataFrame(a)

    df
    Out[10]:
       0     1     2
    0  a   1.2  4.20
    1  b  70.0  0.03
    2  x   5.0  0.00

    df[1].dtype
    Out[11]: dtype('float64')

    实际给出的数据帧中列的格式是否正确