繁体   English   中英

在熊猫数据框中使用逐行应用时,如何保留数据类型?

[英]How do I preserve datatype when using apply row-wise in pandas dataframe?

我遇到一个奇怪的问题,在使用apply功能按行对数据帧不保留值的数据类型的数据帧。 有没有一种方法可以在保留原始数据类型的数据帧上逐行应用功能?

下面的代码演示了此问题。 如果没有在下面的format函数中进行int(...)转换,则会出现错误,因为将数据帧中的int传递给func时已转换为float。

import pandas as pd

df = pd.DataFrame({'int_col': [1, 2], 'float_col': [1.23, 4.56]})
print(df)
print(df.dtypes)

def func(int_and_float):
    int_val, float_val = int_and_float
    print('int_val type:', type(int_val))
    print('float_val type:', type(float_val))
    return 'int-{:03d}_float-{:5.3f}'.format(int(int_val), float_val)

df['string_col'] = df[['int_col', 'float_col']].apply(func, axis=1)
print(df)

这是运行上述代码的输出:

   float_col  int_col
0       1.23        1
1       4.56        2
float_col    float64
int_col        int64
dtype: object
int_val type: <class 'numpy.float64'>
float_val type: <class 'numpy.float64'>
int_val type: <class 'numpy.float64'>
float_val type: <class 'numpy.float64'>
   float_col  int_col           string_col
0       1.23        1  int-001_float-1.230
1       4.56        2  int-002_float-4.560

请注意,即使dfint_col列具有dtype int64 ,但当该列中的值传递给函数func ,它们突然具有numpy.float64 ,我必须在函数的最后一行中使用int(...)转换回来,否则该行将给出错误。

如有必要,我可以按照此处的方式处理此问题,但我真的很想了解为什么会看到这种意外行为。

您的整数越来越upcasted成浮动。 如果可能,Pandas(和NumPy)将尝试将Series(或ndarray)制成单个数据类型。 据我所知,没有详细记录向上转换的规则,但是您可以看到使用numpy.find_common_type如何向上转换不同的类型。

您可以通过在调用apply之前将DataFrame强制转换为“ Object”类型来欺骗Pandas和NumPy保持原始数据类型,如下所示:

df['string_col'] = df[['int_col', 'float_col']].astype('O').apply(func, axis=1)

让我们分解一下这里发生的事情。 首先,执行.astype('O')后df会发生什么?

as_object = df[['int_col', 'float_col']].astype('O')
print(as_object.dtypes)

给出:

int_col      object
float_col    object
dtype: object

好的,现在两列都具有相同的dtype,即object。 我们从之前知道apply() (或从DataFrame中提取一行的任何其他内容)将尝试将两列转换为相同的dtype,但是它将看到它们已经相同,因此无需执行任何操作。

但是,我们仍然能够获得原始的整数和浮点数,因为dtype('O')行为类似于某种可以容纳任何python对象的容器类型。 通常,当Series包含非混合类型(例如字符串和整数)或NumPy无法理解的任何python对象时,可以使用它。

发生的是,当您执行apply(axis = 1)时,输入行将作为熊猫系列传递。 并且,在熊猫中,一系列具有一个dtype。 由于您的行同时具有整数和浮点数,因此整个系列都将转换为浮点数。

import pandas as pd

df = pd.DataFrame({'int_col': [1, 2], 'float_col': [1.23, 4.56]})

def func(int_and_float):
    int_val, float_val = int_and_float
    print('\n')
    print('Prints input series')
    print(int_and_float)
    print('\n')
    return 'int-{:03d}_float-{:5.3f}'.format(int(int_val), float_val)

df['string_col'] = df[['int_col', 'float_col']].apply(func, axis=1)

输出:

Prints input series
int_col      1.00
float_col    1.23
Name: 0, dtype: float64




Prints input series
int_col      2.00
float_col    4.56
Name: 1, dtype: float64

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM