Python 跨不同的时间线和位置使用多个条件创建新的数据帧

Python 跨不同的时间线和位置使用多个条件创建新的数据帧,python,pandas,dataframe,time-series,Python,Pandas,Dataframe,Time Series,我有以下数据帧,其中有一个棘手的问题: Disease State Month Value Covid Texas 2020-03 2 Covid Texas 2020-04 3 Covid Texas 2020-05 4 Covid Texas 2020-08 3 Cancer Florida 2020-04

我有以下数据帧,其中有一个棘手的问题:

Disease  State       Month      Value
Covid    Texas     2020-03        2     
Covid    Texas     2020-04        3     
Covid    Texas     2020-05        4      
Covid    Texas     2020-08        3 
Cancer   Florida   2020-04        4     
Covid    Florida   2020-03        6      
Covid    Florida   2020-04        4      
Flu      Florida   2020-03        5         
我必须列出连续3个月的值,并创建一个新的数据框。 但是,有一些条件:

  • 该列表将针对每个疾病、每个月(从开始到结束:2020年2月至2021年4月)和每个州创建

  • 如果数据集中没有任何特定月份,则将创建该月份的行,该月份的值为0

  • 期望输出:

    Disease State    Month      ValueList
    Covid   Texas    2020-02    [0, 2, 3] (no dataset for Feb 20 but next two months are) 
    Covid   Texas    2020-03    [2, 3, 4] (has values for 3 consecutive months)
    Covid   Texas    2020-04    [3, 4, 0] (doesn’t have value for 6th month)   
    Covid   Texas    2020-05    [4, 0, 0] (has value for present month)
    Covid   Texas    2020-06    [0, 0, 3] (has value for 8th month)
    Covid   Texas    2020-07    [0, 3, 0] (has value for 8th month)
    Covid   Texas    2020-08    [3, 0, 0] (has value for present month)
    Covid   Texas    2020-09    [0, 0, 0] (no dataset for next 3 months)  
    Covid   Texas    2020-10    [0, 0, 0] (no dataset for next 3 months)
    Covid   Texas    2020-11    [0, 0, 0] (no dataset for next 3 months)
    Covid   Texas    2020-12    [0, 0, 0] (no dataset for next 3 months)
    Covid   Texas    2021-01    [0, 0, 0] (no dataset for next 3 months)
    Covid   Texas    2021-02    [0, 0, 0] (no dataset for next 3 months)
    Covid   Texas    2021-03    [0, 0, 0] (no dataset for next 3 months)
    Covid   Texas    2021-04    [0, 0, 0] (no dataset for next 3 months)
    
    我试图用以下方式填写日期:

    df3= (df2.set_index('MonthEnd')
       .groupby(['Disease', 'State']).apply(lambda x: x.drop(['Disease', 'State'], axis=1).asfreq('D'))
       .reset_index())
    
    但是,它不会为每个组返回相同的时间帧。它返回该组中最小日期和最大日期之间的值


    我不知道该怎么开始。任何帮助都将不胜感激。谢谢

    让我们从简单的逻辑开始。因此,基本上您希望为每个组创建从2020年2月到2021年4月的日期范围

    def fill_missing(group):
        group = group.merge(pd.DataFrame({'Month': dates}), how='right')
        group[['Disease', 'State']] = group[['Disease', 'State']].ffill().bfill()
        group['Value'] = group['Value'].fillna(0)
    
        group['ValueList'] = [[a, b, c] for a, b, c in zip(group['Value'].astype(int), group['Value'].shift(-1).fillna(0).astype(int), group['Value'].shift(-2).fillna(0).astype(int))]
    
        return group
    
    df_ = df.groupby(['Disease', 'State']).apply(fill_missing).reset_index(drop=True)
    
    让我们以每组为例,使用reindex添加此日期范围。一旦我完成添加日期范围,现在我将填充数据,然后执行滚动功能以获得3个连续值(考虑前一个值和当前值),并将其转换为列表

    我将把这些列表值分配给我的
    ValueList
    列。 然后我将把所有这些修改过的组添加到dataframe

    解决方案:

    df.Month = pd.to_datetime(df.Month, format="%Y-%m")
    df.set_index('Month',inplace=True)
    
    def add_elem(li): # this is to add 0 elements if rolling function is not getting 2 previous rows. 
        n = (3-len(li))
        if n<3:
            li = [0]*n +li
        return li
    
    
    start = '2020-02'
    end = '2021-04'
    
    data = pd.DataFrame()
    for i,grp in df.groupby(['Disease', 'State']):
        grp = (grp.reindex(pd.date_range(start=start, end=end, freq="MS")))
        grp[['Disease', 'State']] = grp[['Disease', 'State']].bfill().ffill()
        grp = (grp.fillna(0))
        grp['Value'] = grp['Value'].astype(int)
        grp['ValueList'] = ([add_elem(window.to_list()) for window in grp['Value'].rolling(3)])
        data = data.append(grp)
    
    数据:

    df.Month = pd.to_datetime(df.Month, format="%Y-%m")
    df.set_index('Month',inplace=True)
    
    def add_elem(li): # this is to add 0 elements if rolling function is not getting 2 previous rows. 
        n = (3-len(li))
        if n<3:
            li = [0]*n +li
        return li
    
    
    start = '2020-02'
    end = '2021-04'
    
    data = pd.DataFrame()
    for i,grp in df.groupby(['Disease', 'State']):
        grp = (grp.reindex(pd.date_range(start=start, end=end, freq="MS")))
        grp[['Disease', 'State']] = grp[['Disease', 'State']].bfill().ffill()
        grp = (grp.fillna(0))
        grp['Value'] = grp['Value'].astype(int)
        grp['ValueList'] = ([add_elem(window.to_list()) for window in grp['Value'].rolling(3)])
        data = data.append(grp)
    
    疾病 陈述 价值 估价单 2020-02-01 巨蟹座 佛罗里达州 0 [0, 0, 0] 2020-03-01 巨蟹座 佛罗里达州 0 [0, 0, 0] 2020-04-01 巨蟹座 佛罗里达州 4. [0, 0, 4] 2020-05-01 巨蟹座 佛罗里达州 0 [0, 4, 0] 2020-06-01 巨蟹座 佛罗里达州 0 [4, 0, 0] 2020-07-01 巨蟹座 佛罗里达州 0 [0, 0, 0] 2020-08-01 巨蟹座 佛罗里达州 0 [0, 0, 0] 2020-09-01 巨蟹座 佛罗里达州 0 [0, 0, 0] 2020-10-01 巨蟹座 佛罗里达州 0 [0, 0, 0] 2020-11-01 巨蟹座 佛罗里达州 0 [0, 0, 0] 2020-12-01 巨蟹座 佛罗里达州 0 [0, 0, 0] 2021-01-01 巨蟹座 佛罗里达州 0 [0, 0, 0] 2021-02-01 巨蟹座 佛罗里达州 0 [0, 0, 0] 2021-03-01 巨蟹座 佛罗里达州 0 [0, 0, 0] 2021-04-01 巨蟹座 佛罗里达州 0 [0, 0, 0] 2020-02-01 冠状病毒 佛罗里达州 0 [0, 0, 0] 2020-03-01 冠状病毒 佛罗里达州 6. [0, 0, 6] 2020-04-01 冠状病毒 佛罗里达州 4. [0, 6, 4] 2020-05-01 冠状病毒 佛罗里达州 0 [6, 4, 0] 2020-06-01 冠状病毒 佛罗里达州 0 [4, 0, 0] 2020-07-01 冠状病毒 佛罗里达州 0 [0, 0, 0] 2020-08-01 冠状病毒 佛罗里达州 0 [0, 0, 0] 2020-09-01 冠状病毒 佛罗里达州 0 [0, 0, 0] 2020-10-01 冠状病毒 佛罗里达州 0 [0, 0, 0] 2020-11-01 冠状病毒 佛罗里达州 0 [0, 0, 0] 2020-12-01 冠状病毒 佛罗里达州 0 [0, 0, 0] 2021-01-01 冠状病毒 佛罗里达州 0 [0, 0, 0] 2021-02-01 冠状病毒 佛罗里达州 0 [0, 0, 0] 2021-03-01 冠状病毒 佛罗里达州 0 [0, 0, 0] 2021-04-01 冠状病毒 佛罗里达州 0 [0, 0, 0] 2020-02-01 冠状病毒 得克萨斯州 0 [0, 0, 0] 2020-03-01 冠状病毒 得克萨斯州 2. [0, 0, 2] 2020-04-01 冠状病毒 得克萨斯州 3. [0, 2, 3] 2020-05-01 冠状病毒 得克萨斯州 4. [2, 3, 4] 2020-06-01 冠状病毒 得克萨斯州 0 [3, 4, 0] 2020-07-01 冠状病毒 得克萨斯州 0 [4, 0, 0] 2020-08-01 冠状病毒 得克萨斯州 3. [0, 0, 3] 2020-09-01 冠状病毒 得克萨斯州 0 [0, 3, 0] 2020-10-01 冠状病毒 得克萨斯州 0 [3, 0, 0] 2020-11-01 冠状病毒 得克萨斯州 0 [0, 0, 0] 2020-12-01 冠状病毒 得克萨斯州 0 [0, 0, 0] 2021-01-01 冠状病毒 得克萨斯州 0 [0, 0, 0] 2021-02-01 冠状病毒 得克萨斯州 0 [0, 0, 0] 2021-03-01 冠状病毒 得克萨斯州 0 [0, 0, 0] 2021-04-01 冠状病毒 得克萨斯州 0 [0, 0, 0] 2020-02-01 流感 佛罗里达州 0 [0, 0, 0] 2020-03-01 流感 佛罗里达州 5. [0, 0, 5] 2020-04-01 流感 佛罗里达州 0 [0, 5, 0] 2020-05-01 流感 佛罗里达州 0 [5, 0, 0] 2020-06-01 流感 佛罗里达州 0 [0, 0, 0] 2020-07-01 流感 佛罗里达州 0 [0, 0, 0] 2020-08-01 流感 佛罗里达州 0 [0, 0, 0] 2020-09-01 流感 佛罗里达州 0 [0, 0, 0] 2020-10-01 流感 佛罗里达州 0 [0, 0, 0] 2020-11-01 流感 佛罗里达州 0 [0, 0, 0] 2020-12-01 流感 佛罗里达州 0 [0, 0, 0] 2021-01-01 流感 佛罗里达州 0 [0, 0, 0] 2021-02-01 流感 佛罗里达州 0 [0, 0, 0] 2021-03-01 流感 佛罗里达州 0 [0, 0, 0] 2021-04-01 流感 佛罗里达州 0 [0, 0, 0] 您可以使用生成2020年2月至2021年4月之间的日期列表

    dates=pd.date\u范围('2020-02','2021-04',freq='MS').strftime('%Y-%m'))
    
    然后按
    Disease
    State
    列分组,并填充每组中缺失的部分

    def fill_missing(group):
        group = group.merge(pd.DataFrame({'Month': dates}), how='right')
        group[['Disease', 'State']] = group[['Disease', 'State']].ffill().bfill()
        group['Value'] = group['Value'].fillna(0)
    
        group['ValueList'] = [[a, b, c] for a, b, c in zip(group['Value'].astype(int), group['Value'].shift(-1).fillna(0).astype(int), group['Value'].shift(-2).fillna(0).astype(int))]
    
        return group
    
    df_ = df.groupby(['Disease', 'State']).apply(fill_missing).reset_index(drop=True)
    

    签出groupby()并使用此选项填写缺少的日期。您可以使用apply()和groupby()来为每个组添加缺少的日期。一旦分组并添加了日期,您必须每三行迭代并选择一次:对您的Valuelist使用类似df.Value.tolist()的内容columns@JonathanLeon:谢谢你的回复。你能不能也分享一下其他的例子。不幸的是现在不行。在这个问题中,你有很多个人问题。从搜索groupby和apply开始,学习如何迭代和应用函数。我建议你自己尝试一下,并在过程的每一部分提出问题,说明你在哪里尝试过。人们更倾向于帮助修改代码,而不仅仅是提供代码。我已经添加了逻辑。对于我提供的解决方案,可能会有更好的解决方案,但逻辑将保持不变。您好@Pygirl,再次感谢您提供的详细解释。查找类型错误:传递PeriodType数据无效。使用
    data.to_timestamp()
    instead@Roy:请参阅:Hi@Ynjxsjmh。非常感谢你。这种逻辑确实令人印象深刻。在这里,我发现ValueError:您试图在句点[M]和对象列上合并。如果您希望继续,则应使用pd。concat@Roy可能正在将
    Month
    列转换为
    df['Month']=df['Month'].astype(str)
    字符串。