【问题标题】:Get missing dates from datafrane pandas [closed]从数据框熊猫中获取缺失的日期[关闭]
【发布时间】:2021-06-29 17:32:35
【问题描述】:

我想获取列中每个键的缺失日期。我的数据框如下,

     size     number     key      date
0  153.2 K    12345     Hello     20181002
1  153.2 K    12345     No        20181001
2  153.2 K    12345     Hello     20181003
3  153.2 K    12345     No        20181003
4  153.2 K    12345     Hello     20181004
5  153.2 K    12345     No        20181005
6  153.2 K    12345     Hello     20181006

我想得到以下结果

 key        date
  No        20181002
  No        20181004
  Hello     20181005

对于 key="No" 没有日期 20181002、20181004。我想说的是每个键都有不同的日期范围,输出应该缺少特定日期范围内每个键的日期

我使用了以下代码,但它需要两个键的日期,开始日期为 20181001,结束日期为 20181006

import pandas as pd

df = pd.read_csv('4002.csv')
print(df.head(1))

dates = pd.date_range(*pd.to_datetime(df['date'], format='%Y%m%d',errors='coerce').agg(['min', 'max']), freq='D').strftime('%Y%m%d').astype(int)
df1=pd.DataFrame(index=pd.Index(df['key'].unique(), name='key'),columns=dates.difference(df['date'])).reset_index().melt('key').drop(columns=['value'])
print(df1)
df1.to_csv('4002output.csv', index=False)

【问题讨论】:

  • 您的列中的每个日期似乎都有一个值。他们“缺少”什么?我不确定我是否遵循逻辑来获取您的结果数据框。
  • 你的问题不清楚。也许您可以添加更多解释:应显示 Hello 在该范围内开始的日期,例如 Hello 的 startdate 是 20181002,No 是 20181001
  • @jorf.brunning 见stackoverflow.com/questions/68181630/…。提问者基本上要求重新索引
  • @jorf.brunning 抱歉我已经编辑了输出,对于 key="No" 没有日期 20181002、20181004。我想说的是每个键都有不同的日期范围和输出应该缺少特定日期范围内每个键的日期
  • 你为什么不能同时得到Hello 20181001No 20181006

标签: python pandas dataframe date


【解决方案1】:

让我们试试吧:

df['date'] = pd.to_datetime(df['date'], format='%Y%m%d')
midx = pd.MultiIndex.from_frame(
    df.groupby('key')['date'].agg(['min', 'max'])
        .apply(lambda x: pd.date_range(x['min'], x['max']), axis=1)
        .explode()
        .reset_index(),
    names=['key', 'date']
)

new_df = (df.set_index(['key', 'date'])
          .reindex(midx)
          .loc[lambda df_: df_['size'].isna()]
          .index
          .to_frame(index=False)
          .rename(columns={0: 'date'}))

new_df:

     key       date
0  Hello 2018-10-05
1     No 2018-10-02
2     No 2018-10-04

可选的将日期转换回字符串:

new_df['date'] = new_df['date'].dt.strftime('%Y%m%d')
     key      date
0  Hello  20181005
1     No  20181002
2     No  20181004

数据帧:

df = pd.DataFrame({
    'size': ['153.2 K', '153.2 K', '153.2 K', '153.2 K', '153.2 K', '153.2 K',
             '153.2 K'],
    'number': [12345, 12345, 12345, 12345, 12345, 12345, 12345],
    'key': ['Hello', 'No', 'Hello', 'No', 'Hello', 'No', 'Hello'],
    'date': [20181002, 20181001, 20181003, 20181003, 20181004, 20181005,
             20181006]
})

解释:

  1. Groupby aggregate minmax 每个 key 组的值:
df.groupby('key')['date'].agg(['min', 'max'])
             min        max
key                        
Hello 2018-10-02 2018-10-06
No    2018-10-01 2018-10-05
  1. 把它变成Date Range
df.groupby('key')['date'].agg(['min', 'max']) \
        .apply(lambda x: pd.date_range(x['min'], x['max']), axis=1)
key
Hello    DatetimeIndex(['2018-10-02', '2018-10-03', '20...
No       DatetimeIndex(['2018-10-01', '2018-10-02', '20...
dtype: object
  1. explode 分成多行:
df.groupby('key')['date'].agg(['min', 'max']) \
        .apply(lambda x: pd.date_range(x['min'], x['max']), axis=1) \
        .explode()
 
key
Hello   2018-10-02
Hello   2018-10-03
Hello   2018-10-04
Hello   2018-10-05
Hello   2018-10-06
No      2018-10-01
No      2018-10-02
No      2018-10-03
No      2018-10-04
No      2018-10-05
dtype: datetime64[ns]
  1. 把这个框架变成MultiIndex.from_frame
midx = pd.MultiIndex.from_frame(
    df.groupby('key')['date'].agg(['min', 'max'])
        .apply(lambda x: pd.date_range(x['min'], x['max']), axis=1)
        .explode()
        .reset_index(),
    names=['key', 'date']
)

MultiIndex([('Hello', '2018-10-02'),
            ('Hello', '2018-10-03'),
            ('Hello', '2018-10-04'),
            ('Hello', '2018-10-05'),
            ('Hello', '2018-10-06'),
            (   'No', '2018-10-01'),
            (   'No', '2018-10-02'),
            (   'No', '2018-10-03'),
            (   'No', '2018-10-04'),
            (   'No', '2018-10-05')],
           names=['key', 'date'])

其余部分由@ScottBoston 借自this excellent answer

  1. set_index + reindex 与多索引:
df.set_index(['key', 'date'])\
          .reindex(midx)

                     size   number
key   date                           
Hello 2018-10-02  153.2 K  12345.0
      2018-10-03  153.2 K  12345.0
      2018-10-04  153.2 K  12345.0
      2018-10-05      NaN      NaN
      2018-10-06  153.2 K  12345.0
No    2018-10-01  153.2 K  12345.0
      2018-10-02      NaN      NaN
      2018-10-03  153.2 K  12345.0
      2018-10-04      NaN      NaN
      2018-10-05  153.2 K  12345.0
  1. NaN 行与loc 保持一致:
df.set_index(['key', 'date']) \
          .reindex(midx) \
          .loc[lambda df_: df_['size'].isna()]
 
                 size  number
key   date                      
Hello 2018-10-05  NaN     NaN
No    2018-10-02  NaN     NaN
      2018-10-04  NaN     NaN
  1. 把剩下的索引变成to_frame
(df.set_index(['key', 'date'])
 .reindex(midx)
 .loc[lambda df_: df_['size'].isna()]
 .index
 .to_frame(index=False))

     key       date
0  Hello 2018-10-05
1     No 2018-10-02
2     No 2018-10-04

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-25
    • 2014-06-04
    • 1970-01-01
    • 2019-04-08
    • 1970-01-01
    • 2021-11-01
    相关资源
    最近更新 更多