python - 多索引数据框连接(如果不是 NaN 则保留更新的数据并附加到新索引)

标签 python pandas dataframe multi-index

我有两个具有多个索引的 DataFrame,名为 df_basedf_updates。我想将这些 DataFrame 组合成一个 DataFrame 并保留多个索引。

>>> import numpy as np
>>> import pandas as pd
>>> df_base = pd.DataFrame(
...     {
...         "price": {
...             ("2019-01-01", "1001"): 100,
...             ("2019-01-01", "1002"): 100,
...             ("2019-01-01", "1003"): 100,
...             ("2019-01-02", "1001"): 100,
...             ("2019-01-02", "1002"): 100,
...             ("2019-01-02", "1003"): 100,
...             ("2019-01-03", "1001"): 100,
...             ("2019-01-03", "1002"): 100,
...             ("2019-01-03", "1003"): 100,
...         }
...     },
... )
>>> df_base.index.names = ["date", "id"]
>>> df_base.convert_dtypes()
                 price
date       id         
2019-01-01 1001    100
           1002    100
           1003    100
2019-01-02 1001    100
           1002    100
           1003    100
2019-01-03 1001    100
           1002    100
           1003    100
>>>
>>> df_updates = pd.DataFrame(
...     {
...         "price": {
...             ("2019-01-01", "1001"): np.nan,
...             ("2019-01-01", "1002"): 100,
...             ("2019-01-01", "1003"): 100,
...             ("2019-01-02", "1001"): 100,
...             ("2019-01-02", "1002"): 100,
...             ("2019-01-02", "1003"): 100,
...             ("2019-01-03", "1001"): 100,
...             ("2019-01-03", "1002"): 100,
...             ("2019-01-03", "1003"): 100,
...         }
...     }
... )
>>> df_updates.index.names = ["date", "id"]
>>> df_updates.convert_dtypes()
                 price
date       id         
2019-01-01 1001   <NA>
           1002     99
           1003     99
           1004    100

我想将它们与以下规则结合起来:

  1. 如果未指定新数据 (NaN),则保留旧数据
  2. 如果基础 DataFrame 中不存在索引,则附加新数据

我已经尝试使用 .join 但它引发了错误

>>> df_base.join(df_updates)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[48], line 21
     ...

ValueError: columns overlap but no suffix specified: Index(['price'], dtype='object')

即使我添加了后缀,它只会使数据变得更加复杂(需要另一个解决方案)

我也已经尝试使用.update,但是与基础索引不同的新数据未包含在结果中

>>> df_base.update(df_updates)
>>> df_base
                 price
date       id         
2019-01-01 1001  100.0
           1002   99.0
           1003   99.0
2019-01-02 1001  100.0
           1002  100.0
           1003  100.0
2019-01-03 1001  100.0
           1002  100.0
           1003  100.0

最后,我还尝试了一个“棘手”的操作

>>> df_base.update(df_updates)
>>> df_base = df_updates.combine_first(df_base)
>>> df_base
                 price
date       id         
2019-01-01 1001  100.0
           1002   99.0
           1003   99.0
           1004  100.0
2019-01-02 1001  100.0
           1002  100.0
           1003  100.0
2019-01-03 1001  100.0
           1002  100.0
           1003  100.0

这是我预期的结果,但我不确定这是否是这种情况下的最佳解决方案,我尝试使用 %timeit,结果是

>>> %timeit df_base.update(df_updates)
345 µs ± 17.1 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
>>> %timeit df_updates.combine_first(df_base)
1.36 ms ± 10.3 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

当使用大数据时,结果是

>>> %timeit df_base.update(df_updates)
2.38 ms ± 180 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
>>> %timeit df_updates.combine_first(df_base)
9.65 ms ± 400 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

这是适合我的情况的最佳解决方案还是有任何更有效/优化的功能(我期望一个单衬垫 Pandas 功能)?谢谢!

编辑 1:完整代码

import numpy as np
import pandas as pd

df_base = pd.DataFrame(
    {
        "price": {
            ("2019-01-01", "1001"): 100,
            ("2019-01-01", "1002"): 100,
            ("2019-01-01", "1003"): 100,
            ("2019-01-02", "1001"): 100,
            ("2019-01-02", "1002"): 100,
            ("2019-01-02", "1003"): 100,
            ("2019-01-03", "1001"): 100,
            ("2019-01-03", "1002"): 100,
            ("2019-01-03", "1003"): 100,
        }
    },
)
df_base.index.names = ["date", "id"]
df_base.convert_dtypes()


df_updates = pd.DataFrame(
    {
        "price": {
            ("2019-01-01", "1001"): np.nan,
            ("2019-01-01", "1002"): 100,
            ("2019-01-01", "1003"): 100,
            ("2019-01-02", "1001"): 100,
            ("2019-01-02", "1002"): 100,
            ("2019-01-02", "1003"): 100,
            ("2019-01-03", "1001"): 100,
            ("2019-01-03", "1002"): 100,
            ("2019-01-03", "1003"): 100,
        }
    }
)
df_updates.index.names = ["date", "id"]
df_updates.convert_dtypes()

df_base.update(df_updates)
df_base = df_updates.combine_first(df_base)
df_base

最佳答案

您不需要先更新,然后combine_first,只需combine_first即可:

df_base = df_updates.combine_first(df_base)

输出:

                 price
date       id         
2019-01-01 1001  100.0
           1002   99.0
           1003   99.0
           1004  100.0
2019-01-02 1001  100.0
           1002  100.0
           1003  100.0
2019-01-03 1001  100.0
           1002  100.0
           1003  100.0

关于python - 多索引数据框连接(如果不是 NaN 则保留更新的数据并附加到新索引),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76948587/

相关文章:

python - python 模块的完全限定名称

python - 数据框上的多条件过滤器

Python - 循环遍历离散箱列表并选择行

python - 在巨大的数据框架上启用完整的 pandas 摘要

r - 重命名R中的一个命名列

r - 在 R 中将两个数据框列堆叠到一个单独的数据框列中

python - 使用 for 循环打印(大)列表

python - Django/DjangoRestFramework - unittest 未验证使用 ORM 创建的用户

python - 基数为 10 的 int() 无效文字 : 'N/A' Django

python - 如何将 DataFrame 中的值与某些条件进行匹配?