【问题标题】:Pandas: dynamically shifting values across columnsPandas:跨列动态移动值
【发布时间】:2019-05-28 10:55:21
【问题描述】:

我有以下df:

           sales2001   sales2002   sales2003  sales2004
   200012  19.12       0.98 
   200101  19.1        0.98        2.3
   200102  21          0.97        0.8
    ...
   200112  19.12       0.99        2.4
   200201              0.98        2.5
   200202              0.97        0.8        1.2

我想移动内容以使其与时间间隔视图对齐,如下所示:

           sales+1y   sales+2y
   200012  19.12       0.98 
   200101  0.98        2.3       
   200102  0.97        0.8
    ...
   200112  0.99        2.4
   200201  0.98        2.5
   200202  0.8         1.2

基本上将预测数据点与索引的固定时间间隔对齐。 我尝试使用 iterrows 并动态调用给定索引的列,但无法使其工作。大家有什么建议吗?

【问题讨论】:

    标签: python pandas shift


    【解决方案1】:

    justifyDataFrame.dropnaaxis=1 一起使用以删除所有包含至少一个NaN 的列:

    df1 = (pd.DataFrame(justify(df.values, invalid_val=np.nan, side='right'), index=df.index)
              .dropna(axis=1))
    

    如果需要按位置选择最后一列:

    df1 = pd.DataFrame(justify(df.values, invalid_val=np.nan, side='right')[:, -2:],index=df.index)
    

    或者:

    df1 = (pd.DataFrame(justify(df.values, invalid_val=np.nan, side='right'), index=df.index)
            .iloc[:, -2:])
    

    df1.columns = [f'sales+{i+1}y' for i in range(len(df1.columns))]
    print (df1)
            sales+1y  sales+2y
    200012     19.12      0.98
    200101      0.98      2.30
    200102      0.97      0.80
    200112      0.99      2.40
    200201      0.98      2.50
    200202      0.80      1.20
    

    【讨论】:

    • jezrael,看起来很不错。让我用数据试试吧
    • 嗨,Jez,我在这里遇到了一些问题:首先,np.nan 屏蔽失败 cos of float,所以我切换到 pd.null()。第二,我相信正确的理由应该是左吗?还是我误解了这个功能?无论如何,第三个问题是这会返回一个空的df,只有索引..
    • 问题似乎出在 if axis==1: out[justified_mask] = a[mask] 虽然我看到 a[mask] 正确映射真/假,但它没有正确传递给 out ?并且输出是完整的 nan
    • 我不明白如何对掩码进行排序可以将以下数据移动到位。有人有什么解释吗?
    • @lorenzo - 请检查this 更改了适用于一般数据的理由,而不仅仅是数字。
    【解决方案2】:

    另一种选择是使用pd.wide_to_longpivot

    # here I assume the index name is index
    new_df = pd.wide_to_long(df.reset_index(), 'sales', i='index', j='sale_end').reset_index()
    
    # if index is datetime, then use dt.year
    new_df['periods'] = new_df['sale_end'] - new_df['index']//100
    
    # pivot
    new_df.dropna().pivot(index='index',columns='periods', values='sales')
    

    输出:

    periods -1      0       1       2
    idx                 
    200012  NaN     NaN     19.12   0.98
    200101  NaN     19.10   0.98    2.30
    200102  NaN     21.00   0.97    0.80
    200112  NaN     19.12   0.99    2.40
    200201  0.98    2.50    NaN     NaN
    200202  0.97    0.80    1.20    NaN
    

    【讨论】:

    • 好的,我成功了!我对索引类型有一些问题,但已修复。非常感谢,非常有帮助!
    猜你喜欢
    • 2018-10-30
    • 2022-11-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-05
    • 1970-01-01
    • 2020-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多