在熊猫中完成一个不完整的数据框

时间:2019-02-18 16:20:40

标签: pandas python-2.7

早上好。

我有一个像这样的数据框:

df1 = 
    zone   date     p1   p2
0      A      1    154    2
1      B      1   2647    7
2      C      1      0    0
3      A      2   1280    3
4      B      2   6809   20
5      C      2    288    5
6      A      3   2000    4

像这样:

df2 = 
    zone   date     p1   p2
0      A      1    154    2
1      B      1   2647    7
2      C      1      0    0
3      A      2   1280    3
4      B      2   6809   20
5      C      2    288    5

两者之间的区别仅在于可能出现以下情况:一个或几个(但不是全部)区域确实具有最高时间段(列日期)的数据。我希望得到的结果是能够完成数据帧直到某个时间段(在此示例中为3),在每种情况下都可以通过以下方式进行:

df1_result = 
    zone   date     p1   p2
0      A      1    154    2
1      B      1   2647    7
2      C      1      0    0
3      A      2   1280    3
4      B      2   6809   20
5      C      2    288    5
6      A      3   2000    4
7      B      3   6809   20
8      C      3    288    5

df2_result = 
    zone   date     p1   p2
0      A      1    154    2
1      B      1   2647    7
2      C      1      0    0
3      A      2   1280    3
4      B      2   6809   20
5      C      2    288    5
6      A      3   1280    3
7      B      3   6809   20
8      C      3    288    5

我用不同的方法尝试了枢轴和fillna的不同组合,但是我无法获得以前的结果。

我希望我的解释能被理解。

非常感谢。

2 个答案:

答案 0 :(得分:0)

您可以使用reindex为该范围内的所有日期创建条目,然后将最后一个值向前填充。

import pandas as pd

df1 = pd.DataFrame([['A', 1,154, 2],
                    ['B', 1,2647, 7],
                    ['C', 1,0, 0],
                    ['A', 2,1280, 3],
                    ['B', 2,6809, 20],
                    ['C', 2,288, 5],
                    ['A', 3,2000, 4]], 
                   columns=['zone', 'date', 'p1', 'p2'])

result = df1.groupby("zone").apply(lambda x: x.set_index("date").reindex(range(1, 4), method='ffill'))

print(result)

获得

          zone    p1  p2
zone date               
A    1       A   154   2
     2       A  1280   3
     3       A  2000   4
B    1       B  2647   7
     2       B  6809  20
     3       B  6809  20
C    1       C     0   0
     2       C   288   5
     3       C   288   5

答案 1 :(得分:0)

IIUC,您可以从原始pd.MultiIndex重构df,然后使用fillna从您拥有的max的每个子组中获取zone。 / p>

首先,建立索引

ind    = df1.set_index(['zone', 'date']).index
levels = ind.levels
n      = len(levels[0])
labels = [np.tile(np.arange(n), n), np.repeat(np.arange(0, n), n)]

然后,使用pd.MultiIndex构造函数来reindex

df1.set_index(['zone', 'date'])\
   .reindex(pd.MultiIndex(levels= levels, labels= labels))\
   .fillna(df1.groupby(['zone']).max())

            p1      p2
zone    date        
A       1   154.0   2.0
B       1   2647.0  7.0
C       1   0.0     0.0
A       2   1280.0  3.0
B       2   6809.0  20.0
C       2   288.0   5.0
A       3   2000.0  4.0
B       3   6809.0  20.0
C       3   288.0   5.0

要填充df2,只需将最后一行代码中的df1更改为df2,您就会得到

            p1      p2
zone    date        
A       1   154.0   2.0
B       1   2647.0  7.0
C       1   0.0     0.0
A       2   1280.0  3.0
B       2   6809.0  20.0
C       2   288.0   5.0
A       3   2000.0  4.0
B       3   6809.0  20.0
C       3   288.0   5.0

我建议不要直接复制/粘贴代码并尝试运行,而是尝试理解该过程并根据需要进行些微更改,具体取决于原始数据框架与发布的数据有何不同。