更改 pandas 中的列类型

Change column type in pandas

提问人: 提问时间:4/9/2013 最后编辑:cottontail 更新时间:11/6/2023 访问量:3733040

问:

我从列表列表创建了一个 DataFrame:

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

df = pd.DataFrame(table)

如何将列转换为特定类型?在本例中,我想将第 2 列和第 3 列转换为浮点数。

有没有办法在将列表转换为 DataFrame 时指定类型?还是先创建 DataFrame,然后遍历列以更改每列的 dtype?理想情况下,我希望以动态方式执行此操作,因为可能有数百列,并且我不想确切地指定哪些列属于哪种类型。我只能保证每一列都包含相同类型的值。

Python pandas DataFrame 类型 转换

评论


答:

542赞 hernamesbarbara 4/22/2013 #1

使用这个:

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
2503赞 Alex Riley 2/22/2015 #2

在 pandas 中转换类型有四个主要选项:

  1. to_numeric() - 提供将非数字类型(例如字符串)安全地转换为合适的数字类型的功能。(另请参见 to_datetime()to_timedelta()。

  2. astype() - 将(几乎)任何类型转换为(几乎)任何其他类型(即使这样做不一定是明智的)。还允许您转换为分类类型(非常有用)。

  3. infer_objects() - 一种实用方法,用于将包含 Python 对象的对象列转换为 pandas 类型(如果可能)。

  4. convert_dtypes() - 将 DataFrame 列转换为支持的“最佳”dtype(pandas 的对象,用于指示缺失值)。pd.NA

请继续阅读,了解每种方法的更详细解释和用法。


1.to_numeric()

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

此函数将尝试根据需要将非数字对象(例如字符串)更改为整数或浮点数。

基本用法

to_numeric() 的输入是 DataFrame 的 Series 或单列。

>>> 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

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

# convert Series
my_series = pd.to_numeric(my_series)

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

您还可以使用它通过 apply() 方法转换 DataFrame 的多列:

# 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() 还采用一个关键字参数,该参数允许您强制非数字值为 ,或者干脆忽略包含这些值的列。errorsNaN

下面是一个使用具有对象 dtype 的字符串系列的示例:s

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

默认行为是,如果它无法转换值,则引发。在这种情况下,它无法处理字符串“pandas”:

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

与其失败,不如说我们可能希望将“pandas”视为缺失/错误的数值。我们可以使用关键字参数强制无效值如下:NaNerrors

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

第三个选项是在遇到无效值时忽略该操作:errors

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

最后一个选项对于转换整个 DataFrame 特别有用,但不知道我们的哪些列可以可靠地转换为数值类型。在这种情况下,只需写:

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

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

下沉

默认情况下,使用 to_numeric( 进行转换将为您提供 或 dtype(或您的平台原生的任何整数宽度)。int64float64

这通常是您想要的,但是如果您想节省一些内存并使用更紧凑的 dtype,例如 或 ?float32int8

to_numeric() 为您提供了向下转换为 、 、 、 的选项。下面是一系列简单整数类型的示例:'integer''signed''unsigned''float's

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

下放到使用可以保存值的最小整数:'integer'

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

向下转换以类似地选择比正常浮动类型更小的浮动类型:'float'

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

2.astype()

astype() 方法使你能够明确地说明你希望 DataFrame 或 Series 具有的 dtype。它的用途非常广泛,因为您可以尝试从一种类型转到任何其他类型。

基本用法

只需选择一种类型:您可以使用 NumPy dtype(例如)、某些 Python 类型(例如 bool)或特定于 pandas 的类型(例如分类 dtype)。np.int16

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

# 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')

请注意,我说的是“try”——如果 astype() 不知道如何转换 Series 或 DataFrame 中的值,它将引发错误。例如,如果您有一个 or 值,则在尝试将其转换为整数时会遇到错误。NaNinf

从 pandas 0.20.0 开始,可以通过传递 .您的原始对象将原封不动地返回。errors='ignore'

小心

astype() 功能强大,但它有时会“错误地”转换值。例如:

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

这些是小整数,那么转换为无符号 8 位类型以节省内存怎么样?

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

转换奏效了,但 -7 被包裹起来变成了 249(即 28 - 7)!

尝试改用 downcast using 可以帮助防止此错误。pd.to_numeric(s, downcast='unsigned')


3.infer_objects()

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

例如,下面是一个包含两列对象类型的 DataFrame。一个包含实际整数,另一个包含表示整数的字符串:

>>> 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:

>>> df = df.infer_objects()
>>> df.dtypes
a     int64
b    object
dtype: object

列“b”一直被保留,因为它的值是字符串,而不是整数。如果要强制两列都为整数类型,可以改用。df.astype(int)


4.convert_dtypes()

版本 1.0 及更高版本包括一个方法 convert_dtypes(),用于将 Series 和 DataFrame 列转换为支持缺失值的最佳 dtype。pd.NA

这里的“最佳可能”是指最适合保存值的类型。例如,这是一个 pandas 整数类型,如果所有值都是整数(或缺失值):Python 整数对象的 object 列被转换为 ,NumPy 值的列,将成为 pandas dtype 。Int64int32Int32

使用我们的 DataFrame ,我们得到以下结果:objectdf

>>> df.convert_dtypes().dtypes                                             
a     Int64
b    string
dtype: object

由于列“a”保存整数值,因此它被转换为类型(与 不同,它能够保存缺失值)。Int64int64

列“b”包含字符串对象,因此更改为 pandas 的 dtype。string

默认情况下,此方法将从每列中的对象值推断类型。我们可以通过传递来改变这一点:infer_objects=False

>>> df.convert_dtypes(infer_objects=False).dtypes                          
a    object
b    string
dtype: object

现在列“a”仍然是一个对象列:pandas 知道它可以被描述为一个“整数”列(在内部它运行infer_dtype),但没有确切推断它应该具有哪种整数类型,因此没有转换它。列“b”再次转换为“string”dtype,因为它被识别为保存“string”值。

18赞 Harry Stevens 6/14/2017 #3

下面是一个函数,它以 DataFrame 和列列表为参数,并将列中的所有数据强制转换为数字。

# 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')

所以,对于你的例子:

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'])
12赞 MikeyE 7/11/2017 #4

创建两个数据帧,每个数据帧的列具有不同的数据类型,然后将它们追加在一起:

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

结果

In[8}:  d1.dtypes
Out[8]:
float_column     float64
string_column     object
dtype: object

创建数据帧后,可以在第 1 列中使用浮点变量填充数据帧,在第 2 列中使用字符串(或所需的任何数据类型)填充数据帧。

54赞 Akash Nayak 11/15/2017 #5

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

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

代替数据类型,你可以给你的数据类型提供你想要的,比如str、float、int等。

评论

2赞 H. Vabri 1/7/2018
请注意,当使用data_type对包含字符串 ''' 'True' ''' 和 '''' 'False' ''' 的列应用时,所有内容都更改为 .boolTrue
35赞 Thom Ives 10/13/2018 #6

当我只需要指定特定的列,并且我想明确时,我使用了(每个 pandas。DataFrame.astype):

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

因此,使用原始问题,但为其提供列名......

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赞 SarahD 2/1/2019 #7

我以为我有同样的问题,但实际上我有一点不同,使问题更容易解决。对于其他查看此问题的人,值得检查您的输入列表的格式。就我而言,数字最初是浮点数,而不是问题中的字符串:

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

但是,由于在创建数据帧之前对列表进行了过多的处理,我丢失了类型,并且所有内容都变成了字符串。

通过 NumPy 数组创建数据框:

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 列中的条目被视为字符串。然而,做

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')

实际上给出了一个数据框,其中的列格式正确。

28赞 cs95 2/18/2020 #8

熊猫>= 1.0

这张图表总结了熊猫中一些最重要的转化。

Enter image description here

对字符串的转换是微不足道的,图中未显示。.astype(str)

“硬”转化与“软”转化

请注意,此上下文中的“转换”可以指将文本数据转换为其实际数据类型(硬转换),也可以为对象列中的数据推断更合适的数据类型(软转换)。为了说明其中的区别,请看一下

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

a    object
b    object
dtype: object

# Actually converts string to numeric - hard conversion
df.apply(pd.to_numeric).dtypes

a    int64
b    int64
dtype: object

# Infers better data types for object data - soft conversion
df.infer_objects().dtypes

a    object  # no change
b     int64
dtype: object

# Same as infer_objects, but converts to equivalent ExtensionType
    df.convert_dtypes().dtypes
5赞 Sohail 4/6/2020 #9

从 pandas 1.0.0 开始,我们有 .您甚至可以控制要转换的类型!pandas.DataFrame.convert_dtypes

In [40]: df = pd.DataFrame(
    ...:     {
    ...:         "a": pd.Series([1, 2, 3], dtype=np.dtype("int32")),
    ...:         "b": pd.Series(["x", "y", "z"], dtype=np.dtype("O")),
    ...:         "c": pd.Series([True, False, np.nan], dtype=np.dtype("O")),
    ...:         "d": pd.Series(["h", "i", np.nan], dtype=np.dtype("O")),
    ...:         "e": pd.Series([10, np.nan, 20], dtype=np.dtype("float")),
    ...:         "f": pd.Series([np.nan, 100.5, 200], dtype=np.dtype("float")),
    ...:     }
    ...: )

In [41]: dff = df.copy()

In [42]: df 
Out[42]: 
   a  b      c    d     e      f
0  1  x   True    h  10.0    NaN
1  2  y  False    i   NaN  100.5
2  3  z    NaN  NaN  20.0  200.0

In [43]: df.dtypes
Out[43]: 
a      int32
b     object
c     object
d     object
e    float64
f    float64
dtype: object

In [44]: df = df.convert_dtypes()

In [45]: df.dtypes
Out[45]: 
a      Int32
b     string
c    boolean
d     string
e      Int64
f    float64
dtype: object

In [46]: dff = dff.convert_dtypes(convert_boolean = False)

In [47]: dff.dtypes
Out[47]: 
a      Int32
b     string
c     object
d     string
e      Int64
f    float64
dtype: object
8赞 Babatunde Mustapha 3/24/2021 #10

df.info() 为我们提供了 temp 的初始数据类型,即 float64

 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   date    132 non-null    object 
 1   temp    132 non-null    float64

现在,使用以下代码将数据类型更改为 int64:

df['temp'] = df['temp'].astype('int64')

如果再次执行 df.info(),您将看到:

  #   Column  Non-Null Count  Dtype 
 ---  ------  --------------  ----- 
  0   date    132 non-null    object
  1   temp    132 non-null    int64 

这表明您已成功更改列温度的数据类型。 祝您编码愉快!

21赞 Rajeshkanna Purushothaman 9/27/2021 #11
df = df.astype({"columnname": str})

#e.g - 用于将列类型更改为字符串 #df 是您的数据帧

3赞 rubengavidia0x 1/28/2022 #12

如果您有各种对象列,例如 74 个对象列和 2 个 Int 列的 Dataframe,其中每个值都有表示单位的字母:

import pandas as pd 
import numpy as np

dataurl = 'https://raw.githubusercontent.com/RubenGavidia/Pandas_Portfolio.py/main/Wes_Mckinney.py/nutrition.csv'
nutrition = pd.read_csv(dataurl,index_col=[0])
nutrition.head(3)

输出:

    name    serving_size    calories    total_fat    saturated_fat    cholesterol    sodium    choline    folate    folic_acid    ...    fat    saturated_fatty_acids    monounsaturated_fatty_acids    polyunsaturated_fatty_acids    fatty_acids_total_trans    alcohol    ash    caffeine    theobromine    water
0    Cornstarch    100 g    381    0.1g    NaN    0    9.00 mg    0.4 mg    0.00 mcg    0.00 mcg    ...    0.05 g    0.009 g    0.016 g    0.025 g    0.00 mg    0.0 g    0.09 g    0.00 mg    0.00 mg    8.32 g
1    Nuts, pecans    100 g    691    72g    6.2g    0    0.00 mg    40.5 mg    22.00 mcg    0.00 mcg    ...    71.97 g    6.180 g    40.801 g    21.614 g    0.00 mg    0.0 g    1.49 g    0.00 mg    0.00 mg    3.52 g
2    Eggplant, raw    100 g    25    0.2g    NaN    0    2.00 mg    6.9 mg    22.00 mcg    0.00 mcg    ...    0.18 g    0.034 g    0.016 g    0.076 g    0.00 mg    0.0 g    0.66 g    0.00 mg    0.00 mg    92.30 g
3 rows × 76 columns

nutrition.dtypes
name             object
serving_size     object
calories          int64
total_fat        object
saturated_fat    object
                  ...
alcohol          object
ash              object
caffeine         object
theobromine      object
water            object
Length: 76, dtype: object

nutrition.dtypes.value_counts()
object    74
int64      2
dtype: int64

将所有列转换为数字的一个好方法是使用正则表达式将单位替换为 nothing,并使用 astype(float) 将列数据类型更改为 float:

nutrition.index = pd.RangeIndex(start = 0, stop = 8789, step= 1)
nutrition.set_index('name',inplace = True)
nutrition.replace('[a-zA-Z]','', regex= True, inplace=True)
nutrition=nutrition.astype(float)
nutrition.head(3)

输出:

serving_size    calories    total_fat    saturated_fat    cholesterol    sodium    choline    folate    folic_acid    niacin    ...    fat    saturated_fatty_acids    monounsaturated_fatty_acids    polyunsaturated_fatty_acids    fatty_acids_total_trans    alcohol    ash    caffeine    theobromine    water
name
Cornstarch    100.0    381.0    0.1    NaN    0.0    9.0    0.4    0.0    0.0    0.000    ...    0.05    0.009    0.016    0.025    0.0    0.0    0.09    0.0    0.0    8.32
Nuts, pecans    100.0    691.0    72.0    6.2    0.0    0.0    40.5    22.0    0.0    1.167    ...    71.97    6.180    40.801    21.614    0.0    0.0    1.49    0.0    0.0    3.52
Eggplant, raw    100.0    25.0    0.2    NaN    0.0    2.0    6.9    22.0    0.0    0.649    ...    0.18    0.034    0.016    0.076    0.0    0.0    0.66    0.0    0.0    92.30
3 rows × 75 columns

nutrition.dtypes
serving_size     float64
calories         float64
total_fat        float64
saturated_fat    float64
cholesterol      float64
                  ...
alcohol          float64
ash              float64
caffeine         float64
theobromine      float64
water            float64
Length: 75, dtype: object

nutrition.dtypes.value_counts()
float64    75
dtype: int64

现在数据集是干净的,您只能使用正则表达式和 astype() 对此 DataFrame 进行数值运算。

如果要收集单位并粘贴到标题上,可以使用以下代码:cholesterol_mg

nutrition.index = pd.RangeIndex(start = 0, stop = 8789, step= 1)
nutrition.set_index('name',inplace = True)
nutrition.astype(str).replace('[^a-zA-Z]','', regex= True)
units = nutrition.astype(str).replace('[^a-zA-Z]','', regex= True)
units = units.mode()
units = units.replace('', np.nan).dropna(axis=1)
mapper = { k: k + "_" + units[k].at[0] for k in units}
nutrition.rename(columns=mapper, inplace=True)
nutrition.replace('[a-zA-Z]','', regex= True, inplace=True)
nutrition=nutrition.astype(float)
2赞 tdy 3/17/2022 #13

有没有办法在转换为 DataFrame 时指定类型?

是的。其他答案在创建 DataFrame 后转换 dtypes,但我们可以在创建时指定类型。使用或取决于输入格式。DataFrame.from_recordsread_csv(dtype=...)

后者有时是必要的,以避免大数据的内存错误


1. DataFrame.from_records

从所需列类型的结构化数组创建 DataFrame:

x = [['foo', '1.2', '70'], ['bar', '4.2', '5']]

df = pd.DataFrame.from_records(np.array(
    [tuple(row) for row in x], # pass a list-of-tuples (x can be a list-of-lists or 2D array)
    'object, float, int'       # define the column types
))

输出:

>>> df.dtypes
# f0     object
# f1    float64
# f2      int64
# dtype: object

2. read_csv(dtype=...)

如果要从文件中读取数据,请使用参数 在加载时设置列类型。dtyperead_csv

例如,这里我们读取 30M 行,其中 8 位整数和分类:ratinggenre

lines = '''
foo,biography,5
bar,crime,4
baz,fantasy,3
qux,history,2
quux,horror,1
'''
columns = ['name', 'genre', 'rating']
csv = io.StringIO(lines * 6_000_000) # 30M lines

df = pd.read_csv(csv, names=columns, dtype={'rating': 'int8', 'genre': 'category'})

在这种情况下,我们在加载时将内存使用量减半:

>>> df.info(memory_usage='deep')
# memory usage: 1.8 GB
>>> pd.read_csv(io.StringIO(lines * 6_000_000)).info(memory_usage='deep')
# memory usage: 3.7 GB

这是避免大数据内存错误的一种方法。加载并不总是可以更改 dtypes,因为我们可能没有足够的内存来加载默认类型的数据。

3赞 Laurent T 7/6/2022 #14

我有同样的问题。

我找不到任何令人满意的解决方案。我的解决方案只是将这些浮点数转换为 str 并以这种方式删除“.0”。

就我而言,我只是在第一列上应用它:

firstCol = list(df.columns)[0]
df[firstCol] = df[firstCol].fillna('').astype(str).apply(lambda x: x.replace('.0', ''))
1赞 Saeed 12/15/2022 #15

如果你想从字符串格式转换一列,我建议使用这段代码”

import pandas as pd
#My Test Data
data = {'Product': ['A','B', 'C','D'],
          'Price': ['210','250', '320','280']}
data


#Create Data Frame from My data df = pd.DataFrame(data)

#Convert to number
df['Price'] = pd.to_numeric(df['Price'])
df

Total = sum(df['Price'])
Total

否则,如果您要将许多列值转换为数字,我建议您首先过滤您的值并保存在空数组中,然后转换为数字。我希望这段代码能解决你的问题。

10赞 cottontail 2/20/2023 #16

1. 将长浮点数的字符串表示转换为数值

如果一列包含需要精确计算的真正长浮点数的字符串表示形式(会在 15 位数字后四舍五入,甚至更不精确),则从内置库中使用。列的 dtype 将是 but 支持所有算术运算,因此您仍然可以执行矢量化运算,例如算术运算符和比较运算符等。floatpd.to_numericDecimaldecimalobjectdecimal.Decimal

from decimal import Decimal
df = pd.DataFrame({'long_float': ["0.1234567890123456789", "0.123456789012345678", "0.1234567890123456781"]})

df['w_float'] = df['long_float'].astype(float)       # imprecise
df['w_Decimal'] = df['long_float'].map(Decimal)      # precise

res

在上面的示例中,将它们全部转换为相同的数字,同时保持它们的差异:floatDecimal

df['w_Decimal'] == Decimal(df.loc[1, 'long_float'])   # False, True, False
df['w_float'] == float(df.loc[1, 'long_float'])       # True, True, True

2.将长整数的字符串表示转换为整数

默认情况下,转换为 ,如果数字特别长(例如电话号码),则不会起作用 ();尝试(甚至)代替:astype(int)int32OverflowError'int64'float

df['long_num'] = df['long_num'].astype('int64')

顺便说一句,如果得到 ,请打开写入时复制模式(有关详细信息,请参阅此答案)并再次执行您正在执行的任何操作。例如,如果您要转换 并浮点 dtype,则执行以下操作:SettingWithCopyWarningcol1col2

pd.set_option('mode.copy_on_write', True)
df[['col1', 'col2']] = df[['col1', 'col2']].astype(float)

# or use assign to overwrite the old columns and make a new copy
df = df.assign(**df[['col1', 'col2']].astype(float))

3.将整数转换为timedelta

此外,长字符串/整数可能是 datetime 或 timedelta,在这种情况下,请使用 or 转换为 datetime/timedelta dtype:to_datetimeto_timedelta

df = pd.DataFrame({'long_int': ['1018880886000000000', '1590305014000000000', '1101470895000000000', '1586646272000000000', '1460958607000000000']})
df['datetime'] = pd.to_datetime(df['long_int'].astype('int64'))
# or
df['datetime'] = pd.to_datetime(df['long_int'].astype(float))

df['timedelta'] = pd.to_timedelta(df['long_int'].astype('int64'))

res1

4.将时间增量转换为数字

要执行反向操作(将 datetime/timedelta 转换为数字),请将其视为 。如果要构建一个机器学习模型,该模型需要以某种方式将时间(或日期时间)作为数值包含在内,这可能很有用。只需确保如果原始数据是字符串,则必须在转换为数字之前将它们转换为 timedelta 或 datetime。'int64'

df = pd.DataFrame({'Time diff': ['2 days 4:00:00', '3 days', '4 days', '5 days', '6 days']})
df['Time diff in nanoseconds'] = pd.to_timedelta(df['Time diff']).view('int64')
df['Time diff in seconds'] = pd.to_timedelta(df['Time diff']).view('int64') // 10**9
df['Time diff in hours'] = pd.to_timedelta(df['Time diff']).view('int64') // (3600*10**9)

res3

5.将日期时间转换为数字

对于日期时间,日期时间的数字视图是该日期时间与 UNIX 纪元 (1970-01-01) 之间的时间差。

df = pd.DataFrame({'Date': ['2002-04-15', '2020-05-24', '2004-11-26', '2020-04-11', '2016-04-18']})
df['Time_since_unix_epoch'] = pd.to_datetime(df['Date'], format='%Y-%m-%d').view('int64')

res4

6.比astypeto_numeric

df = pd.DataFrame(np.random.default_rng().choice(1000, size=(10000, 50)).astype(str))
df = pd.concat([df, pd.DataFrame(np.random.rand(10000, 50).astype(str), columns=range(50, 100))], axis=1)

%timeit df.astype(dict.fromkeys(df.columns[:50], int) | dict.fromkeys(df.columns[50:], float))
# 488 ms ± 28 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit df.apply(pd.to_numeric)
# 686 ms ± 45.8 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

评论

1赞 Tom Johnson 7/8/2023
很好的答案。对于其他读者,在显示生成的数据框内容时要小心,不要被默认的 Pandas 数值显示精度所迷惑,该精度为 6,如使用 所示。这将使它看起来你的精度不如实际情况。您可以将类似的东西与 pd.option_context('display.float_format', '{:0.20f}'.format): print(df) 一起使用来查看 20 位数字。pd.options.display.precision