熊猫:将 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】:将对象转换为数字int
或float
。
代码是:--
df["total_sqft"] = pd.to_numeric(df["total_sqft"], errors='coerce').fillna(0, downcast='infer')
【讨论】:
以上是关于熊猫:将 dtype 'object' 转换为 int的主要内容,如果未能解决你的问题,请参考以下文章