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

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

df = pd.DataFrame(table)

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

是否有一种方法可以在转换到DataFrame时指定类型?还是先创建DataFrame,然后循环遍历列以更改每列的类型更好?理想情况下,我希望以动态的方式进行此操作,因为可能有数百个列,而我不想确切地指定哪些列属于哪种类型。我所能保证的是每一列都包含相同类型的值。


当前回答

我以为我有同样的问题,但实际上我有一个轻微的差异,使问题更容易解决。对于其他研究这个问题的人来说,检查输入列表的格式是值得的。在我的情况下,数字最初是浮点数,而不是问题中的字符串:

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

但是在创建dataframe之前过多地处理列表,我丢失了类型,所有内容都变成了字符串。

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

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

其他回答

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

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

将所有列转换为数值的一个好方法是使用正则表达式来替换单位,并使用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

现在数据集是干净的,你只能用regex和astype()对这个数据帧进行数值操作。

如果你想收集单位,并粘贴在标题如胆固醇,你可以使用下面的代码:

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)

创建两个数据框架,每个数据框架的列都有不同的数据类型,然后将它们附加在一起:

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

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

从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

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

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

在数据类型的地方,你可以给出你想要的数据类型,比如,str, float, int等。

用这个:

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