【问题标题】:pandas: Fill missing dates when keeping duplicates熊猫:保留重复时填写缺失的日期
【发布时间】:2019-04-02 17:51:28
【问题描述】:

我有一个简单的pandas 系列:

import pandas as pd

quantities = [1, 14, 14, 11, 12, 13, 14]
timestamps = [pd.Timestamp(2015, 4, 1), pd.Timestamp(2015, 4, 1), pd.Timestamp(2015, 4, 2), pd.Timestamp(2015, 4, 3), pd.Timestamp(2015, 4, 4), pd.Timestamp(2015, 4, 5), pd.Timestamp(2015, 4, 8)]
series = pd.Series(quantities, index=timestamps)

如下所示:

2015-04-01     1
2015-04-01    14
2015-04-02    14
2015-04-03    11
2015-04-04    12
2015-04-05    13
2015-04-08    14
dtype: int64

我想填写缺失的日期,即2015-04-06 = NaN2015-04-07 = NaN,但保持系列不变,即:

2015-04-01     1
2015-04-01    14
2015-04-02    14
2015-04-03    11
2015-04-04    12
2015-04-05    13
2015-04-06    NaN
2015-04-07    NaN
2015-04-08    14
dtype: int64

我试过了:

series = series.asfreq('D')

但出现以下错误:ValueError: cannot reindex from a duplicate axis。发生此错误是因为重复的时间戳值。

地球上有什么方法可以做到这一点吗?

感谢您的帮助。

【问题讨论】:

  • reset_index() 应该可以帮助你,除此之外,看不到清晰的路径

标签: python pandas


【解决方案1】:

让我们试试吧:

s = pd.Series(np.nan, index=pd.date_range(series.index.min(), series.index.max(), freq='D'))
pd.concat([series,s[~s.index.isin(series.index)]]).sort_index()

输出:

2015-04-01     1.0
2015-04-01    14.0
2015-04-02    14.0
2015-04-03    11.0
2015-04-04    12.0
2015-04-05    13.0
2015-04-06     NaN
2015-04-07     NaN
2015-04-08    14.0
dtype: float64

时间安排:

%%timeit
temp = series[~series.index.duplicated(keep='first')].asfreq('D')
pd.concat([series, temp.loc[~temp.index.isin(series.index)]]).sort_index()

每个循环 2.51 ms ± 52.7 µs(平均值 ± 标准偏差,7 次运行,每次 100 个循环)

%%timeit
series.name = "x"
calendar = pd.DataFrame(None, index=pd.DatetimeIndex(start=series.index.min(), end=series.index.max(), freq='D'))
calendar.join(series)

C:\ProgramData\Anaconda3\lib\site-packages\ipykernel_launcher.py:2: FutureWarning:通过传递范围端点创建 DatetimeIndex 是 已弃用。请改用pandas.date_range

每个循环 2.07 ms ± 27.1 µs(平均值 ± 标准偏差,7 次运行,每次 100 个循环)

%%timeit
s = pd.Series(np.nan, index=pd.date_range(series.index.min(), series.index.max(), freq='D'))
pd.concat([series,s[~s.index.isin(series.index)]]).sort_index()

每个循环 1.86 毫秒 ± 15.4 微秒(平均值 ± 标准偏差,7 次运行,每次 1000 次循环)

感谢@root 的建议。

%%timeit
s = pd.Series(index=pd.date_range(series.index.min(), series.index.max(), freq='D')\
                      .difference(series.index))
pd.concat([series,s]).sort_index()

每个循环 1.55 毫秒 ± 11.6 微秒(平均值 ± 标准偏差,7 次运行,每次 1000 次循环)

【讨论】:

  • 我的回答是最慢的,但我在这里学到了更好的东西,干得好!
  • @Terry 谢谢。这就是我喜欢SO的原因。我每天都学到一些东西。
  • 将索引设置为index = pd.date_range(...).difference(series.index)可能会快一点,然后可以避免isin/布尔索引和直接concat两者。
  • @root 好主意...让我们试试吧。
  • @ScottBoston 非常感谢这个非常详细的答案。
【解决方案2】:

这应该足够了,假设您没有数百万行:

series.name = "x"
calendar = pd.DataFrame(None, index=pd.DatetimeIndex(start=series.index.min(), end=series.index.max(), freq='D'))
calendar.join(series)

输出:

               x
2015-04-01   1.0
2015-04-01  14.0
2015-04-02  14.0
2015-04-03  11.0
2015-04-04  12.0
2015-04-05  13.0
2015-04-06   NaN
2015-04-07   NaN
2015-04-08  14.0

如果你想要一个系列,你可以访问结果 DataFrame 的 x 列:calendar.join(series).x

【讨论】:

    【解决方案3】:

    您可以使用pandas.concat。添加到您的示例代码:

    series2 = pd.Series([pd.np.nan, pd.np.nan],
                        index=[pd.Timestamp(2015, 4, 6), 
                               pd.Timestamp(2015, 4, 7)])
    
    pd.concat([series, series2], axis=0).sort_index()
    

    返回

    2015-04-01     1.0
    2015-04-01    14.0
    2015-04-02    14.0
    2015-04-03    11.0
    2015-04-04    12.0
    2015-04-05    13.0
    2015-04-06     NaN
    2015-04-07     NaN
    2015-04-08    14.0
    dtype: float64
    

    也就是说,使用非唯一索引会让您面临更多困难。您将受益于使用唯一的索引级别或非索引字段来消除歧义。

    【讨论】:

    • 如果你想在所有地方都使用相同的值,你可以将一个标量传递给pd.Seriespd.Series(pd.np.nan, index=[pd.Timestamp(2015, 4, 6), pd.Timestamp(2015, 4, 7)])
    【解决方案4】:

    您可以使用asfreq 删除索引重复项,然后在temp.index 不在原始系列中的位置连接

    temp = series[~series.index.duplicated(keep='first')].asfreq('D')
    pd.concat([series, temp.loc[~temp.index.isin(series.index)]]).sort_index()
    
    output:
    2015-04-01     1.0
    2015-04-01    14.0
    2015-04-02    14.0
    2015-04-03    11.0
    2015-04-04    12.0
    2015-04-05    13.0
    2015-04-06     NaN
    2015-04-07     NaN
    2015-04-08    14.0
    dtype: float64
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-14
      • 1970-01-01
      • 2018-04-24
      • 1970-01-01
      • 1970-01-01
      • 2017-12-12
      • 1970-01-01
      相关资源
      最近更新 更多