熊猫:将 dtype 'object' 转换为 int

Posted

技术标签:

【中文标题】熊猫:将 dtype \'object\' 转换为 int【英文标题】:Pandas: convert dtype 'object' to int熊猫:将 dtype 'object' 转换为 int 【发布时间】:2017-01-03 13:40:54 【问题描述】:

我在 Pandas 中读取了一个 SQL 查询,其值以 dtype 'object' 的形式出现,尽管它们是字符串、日期和整数。我能够将日期“对象”转换为 Pandas 日期时间 dtype,但在尝试转换字符串和整数时出现错误。

这是一个例子:

>>> import pandas as pd
>>> df = pd.read_sql_query('select * from my_table', conn)
>>> df
    id    date          purchase
 1  abc1  2016-05-22    1
 2  abc2  2016-05-29    0
 3  abc3  2016-05-22    2
 4  abc4  2016-05-22    0

>>> df.dtypes
 id          object
 date        object
 purchase    object
 dtype: object

df['date'] 转换为日期时间有效:

>>> pd.to_datetime(df['date'])
 1  2016-05-22
 2  2016-05-29
 3  2016-05-22
 4  2016-05-22
 Name: date, dtype: datetime64[ns] 

但在尝试将df['purchase'] 转换为整数时出现错误:

>>> df['purchase'].astype(int)
 ....
 pandas/lib.pyx in pandas.lib.astype_intsafe (pandas/lib.c:16667)()
 pandas/src/util.pxd in util.set_value_at (pandas/lib.c:67540)()

 TypeError: long() argument must be a string or a number, not 'java.lang.Long'

注意:当我尝试 .astype('float') 时,我遇到了类似的错误

当尝试转换为字符串时,似乎什么也没有发生。

>>> df['id'].apply(str)
 1 abc1
 2 abc2
 3 abc3
 4 abc4
 Name: id, dtype: object

【问题讨论】:

我猜,试试df['purchase'].astype(str).astype(int) 没有字符串 dtype。它保持为对象。对于另一个,尝试更通用的pd.to_numeric(df['purchase']),如果成功,您可以添加.astype(int) @piRSquared - 是的,这行得通。 @ayhan - 我在尝试 pd.to_numeric 时收到此错误 - TypeError: Invalid object type 如果列包含 NaN 和整数,则接受的答案将不起作用。为此,如果您有 pandas 1.x,则需要使用 convert_dtypes,或者在旧版本上使用 infer_objects 【参考方案1】:

根据@piRSquared 的评论记录对我有用的答案。

我需要先转换为字符串,然后是整数。

>>> df['purchase'].astype(str).astype(int)

【讨论】:

需要先转换为 str 再转换为 int 多么烦人!我不明白为什么会这样。 您需要将其分配给同一列(或不同的列)以保持更改,它不是“就地”完成的。而且您不必总是先转换为str 我收到“invalid literal for int() with base 10: 'DEFAULT' error message. df['purchase'] = df['purchase'].astype(int) 应该可以工作。我认为错误是由数据引起的。【参考方案2】:

很简单

pd.factorize(df.purchase)[0]

例子:

labels, uniques = pd.factorize(['b', 'b', 'a', 'c', 'b'])`
labels
# array([0, 0, 1, 2, 0])
uniques
# array(['b', 'a', 'c'], dtype=object)

【讨论】:

嗯?!更多评论可以使这一点更加清晰 不知道为什么它会得到两个反对票。它似乎适用于更普遍的情况。为我工作 这是一个转换问题,而不是分解问题,也许这就是为什么@FlowingCloud【参考方案3】:

按照以下步骤操作:

1.clean 你的文件 -> 以csv 格式打开你的数据文件,看看有没有“?”代替空的地方并将它们全部删除。

2.drop 包含缺失值的行 例如:

df.dropna(subset=["normalized-losses"], axis = 0 , inplace= True)

3.现在使用 astype 进行转换

df["normalized-losses"]=df["normalized-losses"].astype(int)

注意:如果您的程序仍然发现错误,请再次检查您的csv 文件,在 excel 中打开它以查找是否有“?”在您需要的列中,然后将其删除并保存文件并返回并运行您的程序。

评论成功!如果它有效。 :)

【讨论】:

并非所有文件都可以在 Excel 中打开以进行此类检查。【参考方案4】:

我的火车数据包含三个特征是应用astype之后的对象,它将对象转换为数字,但在此之前,您需要执行一些预处理步骤:

train.dtypes

C12       object
C13       object
C14       Object

train['C14'] = train.C14.astype(int)

train.dtypes

C12       object
C13       object
C14       int32

【讨论】:

【参考方案5】:

熊猫 >= 1.0

convert_dtypes

(自我)接受的答案没有考虑到对象列中存在 NaN 的可能性。

df = pd.DataFrame(
     'a': [1, 2, np.nan], 
     'b': [True, False, np.nan], dtype=object) 
df                                                                         

     a      b
0    1   True
1    2  False
2  NaN    NaN

df['a'].astype(str).astype(int) # raises ValueError

这会阻塞,因为 NaN 被转换为字符串“nan”,并且进一步尝试强制转换为整数将失败。为避免此问题,我们可以使用 convert_dtypes 将列软转换为对应的 nullable type:

df.convert_dtypes()                                                        

      a      b
0     1   True
1     2  False
2  <NA>   <NA>

df.convert_dtypes().dtypes                                                 

a      Int64
b    boolean
dtype: object

如果您的数据中混有垃圾文本,您可以使用pd.to_numeric 作为初始步骤:

s = pd.Series(['1', '2', '...'])
s.convert_dtypes()  # converts to string, which is not what we want

0      1
1      2
2    ...
dtype: string 

# coerces non-numeric junk to NaNs
pd.to_numeric(s, errors='coerce')

0    1.0
1    2.0
2    NaN
dtype: float64

# one final `convert_dtypes` call to convert to nullable int
pd.to_numeric(s, errors='coerce').convert_dtypes() 

0       1
1       2
2    <NA>
dtype: Int64

【讨论】:

【参考方案6】:

无法发表评论,因此将其发布为答案,这有点介于@piRSquared/@cyril 的解决方案和@cs95 的解决方案之间:

正如@cs95 所指出的,如果您的数据包含 NaN 或 None,则转换为字符串类型将在之后尝试转换为 int 时引发错误。

但是,如果您的数据由(数字)字符串组成,则使用convert_dtypes 会将其转换为字符串类型,除非您按照@cs95 的建议使用pd.to_numeric(可能与df.apply() 结合使用)。

如果您的数据仅包含数字字符串(包括 NaN 或 None,但没有任何非数字“垃圾”),一个可能更简单的替代方法是先转换为浮点数,然后转换为 nullable-integer extension dtypes 之一由 pandas 提供(已经存在于 0.24 版中)(另见answer):

df['purchase'].astype(float).astype('Int64')

请注意,最近在 github 上对此进行了讨论(尽管目前是一个未解决的已关闭问题),并且对于非常长的 64 位整数,您可能必须显式转换为 float128 以避免转换期间的近似值。

【讨论】:

【参考方案7】:

This was my data

## list of columns 
l1 = ['PM2.5', 'PM10', 'TEMP', 'BP', ' RH', 'WS','CO', 'O3', 'Nox', 'SO2'] 

for i in l1:
 for j in range(0, 8431): #rows = 8431
   df[i][j] = int(df[i][j])

我建议您仅将其用于小数据。这段代码的复杂度为 O(n^2)。

【讨论】:

这个解决方案似乎不如许多现有的解决方案,为什么选择这个? .astype() 方法在我的代码中不起作用。所以我使用 int() func 将每个项目转换为整数 .astype() 方法在我的代码中不起作用。 你能更具体一点吗? 所以我使用 int() func 将每个项目转换为整数 如果有必要,那么您应该使用 Series.map()DataFrame.applymap()【参考方案8】:

就我而言,我有一个包含混合数据的 df:

df:
                     0   1   2    ...                  242                  243                  244
0   2020-04-22T04:00:00Z   0   0  ...          3,094,409.5         13,220,425.7          5,449,201.1
1   2020-04-22T06:00:00Z   0   0  ...          3,716,941.5          8,452,012.9          6,541,599.9
....

花车实际上是对象,但我需要它们是真正的花车。

要修复它,请参考上面@AMC 的评论:

def coerce_to_float(val):
    try:
       return float(val)
    except ValueError:
       return val

df = df.applymap(lambda x: coerce_to_float(x))

【讨论】:

【参考方案9】:
df['col_name'] = pd.to_numeric(df['col_name'])

这是一个更好的选择

【讨论】:

你能解释一下为什么它更好吗?【参考方案10】:

要更改数据类型并保存到数据框中,需要替换新的数据类型如下:

ds["cat"] = pd.to_numeric(ds["cat"]) 或 ds["cat"] = ds["cat"].astype(int)

【讨论】:

【参考方案11】:

如果这些方法失败,您可以尝试这样的列表推导:

df["int_column"] = [int(x) if x.isnumeric() else x for x in df["str_column"] ]

【讨论】:

【参考方案12】:

将对象转换为数字intfloat

代码是:--

df["total_sqft"] = pd.to_numeric(df["total_sqft"], errors='coerce').fillna(0, downcast='infer')

【讨论】:

以上是关于熊猫:将 dtype 'object' 转换为 int的主要内容,如果未能解决你的问题,请参考以下文章

使用转换的熊猫分组列表聚合失败并出现键错误

在熊猫中如何将符号转换为整数?

熊猫数据框可以有列表的dtype吗?

从数据框或系列的熊猫输出中删除名称、dtype

如何将熊猫系列的列值转换为Python中的列表?

转换熊猫数据框中的分类数据