使用无间隙日期范围作为索引来转动Pandas数据帧

时间:2014-10-09 02:00:42

标签: python python-2.7 pandas

问题:标题为条件,如何获得下面显示的结果?

示例数据:

     Date       Client      Order
0    1/30/1987  AAA         O.N. 111
1    3/28/1987  BBB         O.N. 112
2    3/28/1987  CCC         O.N. 113
3    3/28/1987  AAA         O.N. 114
4    3/31/1987  DDD         O.N. 115
5    3/31/1987  BBB         O.N. 116
6    3/31/1987  EEE         O.N. 117
7    4/1/1987   FFF         O.N. 118
8    4/1/1987   CCC         O.N. 119
9    4/1/1987   AAA         O.N. 120
10   4/2/1987   DDD         O.N. 121

期望的结果:

            AAA BBB CCC DDD EEE FFF
1987-01-30  111 NaN NaN NaN NaN NaN
1987-01-31  NaN NaN NaN NaN NaN NaN
1987-02-01  NaN NaN NaN NaN NaN NaN
...
1987-03-28  114 112 113 NaN NaN NaN
...
1987-03-31  NaN 116 NaN 115 117 NaN
1987-04-01  120 NaN 119 NaN NaN 118
1987-04-02  NaN NaN NaN 121 NaN NaN

尝试了方法:

# Results to an error.
df_p = df.pivot(index='Date',columns='Client',values='Order')

# Almost there, but I don't want to iterate over each cell to get Order number.
df_symbol = df['Client']
df_symbol_unique = set(df_symbol)
index = pd.date_range(df['Date'].iat[0],df['Date'].iat[-1])
df_new = pd.DataFrame(np.NaN,index=index,columns=sorted(list(df_symbol_unique)))

#               AAA BBB CCC DDD EEE FFF
#1987-01-30     NaN NaN NaN NaN NaN NaN
#1987-01-31     NaN NaN NaN NaN NaN NaN
#1987-02-01     NaN NaN NaN NaN NaN NaN
#...

检查了相关链接(似乎没有解决问题):

  1. concat pandas DataFrame along timeseries indexes
  2. transpose multiple columns Pandas dataframe
  3. 备注:

    1. Date列始终从最旧到最新排序。
    2. 客户永远不会超过1个订单/天。
    3. 日期范围内必须没有间隙,因此上面给出了index
    4. 更新

      显然,在以后的日期确实存在重复的客户订单对,这与上面的注释2相反,这就是弄乱我的数据(这么多只检查一百万行中的20,000行,pfft)和枢轴。 DSM的答案(以及我最初的预感)是正确的,即枢轴是解决方案。

      鉴于此,我在想,是否有可能使用计数代替每个客户的订单,而不是自己获取订单号?

      更新2:

      抄袭DSM的答案,但改为使用pivot_table

      df["Date"] = pd.to_datetime(df["Date"])
      df_p = df.pivot_table(rows="Date", cols="Client", values="Order", aggfunc=len)
      df_p = df_p.reindex(pd.date_range(df_p.index.min(), df_p.index.max()))
      

      在修改后的表格上提供以下输出:

      Client      AAA  BBB  CCC  DDD  EEE  FFF
      1987-01-30    1  NaN  NaN  NaN  NaN  NaN
      1987-01-31  NaN  NaN  NaN  NaN  NaN  NaN
      1987-02-01  NaN  NaN  NaN  NaN  NaN  NaN
      1987-02-02  NaN  NaN  NaN  NaN  NaN  NaN
      1987-02-03  NaN  NaN  NaN  NaN  NaN  NaN
      
      [5 rows x 6 columns]
      Client      AAA  BBB  CCC  DDD  EEE  FFF
      1987-03-29  NaN  NaN  NaN  NaN  NaN  NaN
      1987-03-30  NaN  NaN  NaN  NaN  NaN  NaN
      1987-03-31  NaN    1  NaN    1    1  NaN
      1987-04-01    2  NaN  NaN  NaN  NaN    1
      1987-04-02  NaN  NaN  NaN    1  NaN  NaN
      
      [5 rows x 6 columns]
      [Finished in 1.4s]
      

      对我来说已经足够了。

1 个答案:

答案 0 :(得分:2)

这样的事情 - 看起来与你所尝试的非常相似,说实话 - 对我有用:

>>> df
         Date Client     Order
0   1/30/1987    AAA  O.N. 111
1   3/28/1987    BBB  O.N. 112
2   3/28/1987    CCC  O.N. 113
3   3/28/1987    AAA  O.N. 114
4   3/31/1987    DDD  O.N. 115
5   3/31/1987    BBB  O.N. 116
6   3/31/1987    EEE  O.N. 117
7    4/1/1987    FFF  O.N. 118
8    4/1/1987    CCC  O.N. 119
9    4/1/1987    AAA  O.N. 120
10   4/2/1987    DDD  O.N. 121
>>> df["Date"] = pd.to_datetime(df["Date"])
>>> df["Order"] = df["Order"].str.split().str[-1]
>>> df_p = df.pivot(index="Date", columns="Client", values="Order")
>>> df_p = df_p.reindex(pd.date_range(df_p.index.min(), df_p.index.max()))

给出:

>>> df_p.head()
Client      AAA  BBB  CCC  DDD  EEE  FFF
1987-01-30  111  NaN  NaN  NaN  NaN  NaN
1987-01-31  NaN  NaN  NaN  NaN  NaN  NaN
1987-02-01  NaN  NaN  NaN  NaN  NaN  NaN
1987-02-02  NaN  NaN  NaN  NaN  NaN  NaN
1987-02-03  NaN  NaN  NaN  NaN  NaN  NaN
>>> df_p.tail()
Client      AAA  BBB  CCC  DDD  EEE  FFF
1987-03-29  NaN  NaN  NaN  NaN  NaN  NaN
1987-03-30  NaN  NaN  NaN  NaN  NaN  NaN
1987-03-31  NaN  116  NaN  115  117  NaN
1987-04-01  120  NaN  119  NaN  NaN  118
1987-04-02  NaN  NaN  NaN  121  NaN  NaN