在pandas数据框中使用行方式时,如何保留数据类型?

时间:2017-11-06 18:43:47

标签: python pandas

我遇到了一个奇怪的问题,即在数据帧上逐行使用apply函数不会保留数据帧中值的数据类型。有没有办法在保留原始数据类型的数据帧上逐行应用函数?

下面的代码演示了这个问题。如果没有int(...)函数中的format转换,则会出现错误,因为数据框中的int在传递到func时会转换为浮点数。

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

请注意,即使int_col的{​​{1}}列有dtype df,当该列的值传递到函数int64时,它们突然显示为{{1}我必须在函数的最后一行使用func来转换回来,否则该行会产生错误。

如果有必要的话,我可以按照这里的方式处理这个问题,但我真的很想知道为什么我会看到这种意想不到的行为。

2 个答案:

答案 0 :(得分:3)

您的整体已经上传成为花车。如果可能,Pandas(和NumPy)将尝试将Series(或ndarray)制作为单个数据类型。据我所知,上传的确切规则没有记录,但你可以看到使用numpy.find_common_type如何提升不同的类型。

您可以通过将DataFrame转换为类型&#34;对象&#34;来欺骗Pandas和NumPy以保持原始数据类型。在调用apply之前,像这样:

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,即对象。我们从之前就知道apply()(或者从DataFrame中提取一行的任何其他内容)会尝试将两列转换为相同的dtype,但是会看到它们已经相同,所以没有什么可做的

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

答案 1 :(得分:1)

当你申请(轴= 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