【问题标题】:Pandas 'Int64' type is converted to an 'object' type after mergePandas 'Int64' 类型在合并后转换为 'object' 类型
【发布时间】:2020-03-01 00:13:52
【问题描述】:

我在使用Int64 时注意到以下行为。有没有办法避免类型转换并保留 Int64 类型后合并?

df1 = pd.DataFrame(data={'col1': [1, 2, 3, 4, 5], 'col2': [10, 11, 12, 13, 14]}, dtype=pd.Int64Dtype())
df2 = pd.DataFrame(data={'col1': [1, 2, 3], 'col2': [10, 11, 12]}, dtype=pd.Int64Dtype())
df = df2.merge(df1, how='outer', indicator=True, suffixes=('_x', ''))

df1.dtypes
Out[8]: 
col1    Int64
col2    Int64
dtype: object

df2.dtypes
Out[9]: 
col1    Int64
col2    Int64
dtype: object

df.dtypes
Out[10]: 
col1        object
col2        object
_merge    category
dtype: object

我应该澄清一下,我正在寻找一个不涉及明确执行以下操作的答案:

for k, v in df1.dtypes.to_dict().items():
    df[k] = df[k].astype(v)

【问题讨论】:

  • github.com/pandas-dev/pandas/issues/8596,我认为问题是什么时候做 external ,pandas 将列类型设置为将来的对象np.nan
  • 升级熊猫。我在0.24.2 版本上尝试了您的代码,它保留了dtypes
  • @Mstaino 我在 0.25.1。你没有使用 'Int64' - 你必须使用 'int64'。
  • 不,我照原样复制了您的前两行代码。现在我正在检查我所做的是使用df1.merge 而不是df2.merge。奇怪
  • @Mstaino 这与 df1 包含所有 df2 并且如果我们要 isin() df1 和 df2 没有 nan 值(导致类型更改)这一事实有关 - 很难解释但是如果您尝试使用 isin() 从 df1 中删除所有 df2 会变得很明显 - 它会将列转换为浮点数。

标签: python pandas dataframe


【解决方案1】:

它来自需要重新索引 df2(基本数据帧)需要重新索引以匹配 df1(合并数据帧)。它可能应该像您预期的那样运行,但使用 pandas Int64Dtype 类型而不是 python int 类型是一个边缘情况。

在执行合并时,会调用此重新索引:

> /home/tron/.local/lib/python3.7/site-packages/pandas/core/reshape/merge.py(840)_maybe_add_join_keys()
    838                     key_col = rvals
    839                 else:
--> 840                     key_col = Index(lvals).where(~mask, rvals)
    841 
    842                 if result._is_label_reference(name):

然后调用此数组 dtype。

> /home/tron/.local/lib/python3.7/site-packages/pandas/core/indexes/base.py(359)__new__()
    357                 data = ea_cls._from_sequence(data, dtype=dtype, copy=False)
    358             else:
--> 359                 data = np.asarray(data, dtype=object)
    360 
    361             # coerce to the object dtype

您可以通过使用 pdb 调试器并单步执行结果来自行探索。

df1 = pd.DataFrame(data={'col1': [1, 2, 3, 4, 5], 'col2': [10, 11, 12, 13, 14]}, dtype=pd.Int64Dtype())
df2 = pd.DataFrame(data={'col1': [1, 2, 3], 'col2': [10, 11, 12]}, dtype=pd.Int64Dtype())
def test():
    import pdb
    pdb.set_trace()
    df = df2.merge(df1, how='outer', indicator=True, suffixes=('_x', ''))
    return df
df = text()

一些有趣的笔记:

  • 如果您使用dtype=int 而不是dtype=pd.Int64Dtype(),则类型实际上符合预期。它可能应该与两者类似,但int 类型在pandas/core/indexes/base.py(359)__new__() 中具有不同的逻辑路径,它将 int 解释为“# index-like. That said, you should likely default to using the default int, float, bool` 来自 python 而不是 pandas dtypes 的类型,除非你有一个特定的用例。

  • df2.merge(df1, how='inner') 保留类型,因为不需要重新索引。

  • df1.merge(df2, how='outer') 保留类型,因为 df1(基本数据帧)不需要重新索引来合并 df2。

【讨论】:

    猜你喜欢
    • 2019-06-22
    • 2018-11-12
    • 1970-01-01
    • 2023-01-26
    • 2020-04-13
    • 2011-07-03
    • 2019-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多