Pandas: 合并数据框、向前填充和列数据的多级索引

5

我有两个csv文件,它们具有相同的列名,但是不同的值。

第一列是索引(time),其中一个数据列是唯一标识符(id

每个csv文件的索引(time)都不同。

我已经使用read_csv将数据读入了两个数据框,得到以下结果:

        +-------+------+-------+
        | id    | size | price |
+-------+-------+------+-------+
| time  |       |      |       |
+-------+-------+------+-------+
| t0    | ID1   | 10   | 110   |
| t2    | ID1   | 12   | 109   |
| t6    | ID1   | 20   | 108   |
+-------+-------+------+-------+

        +-------+------+-------+
        | id    | size | price |
+-------+-------+------+-------+
| time  |       |      |       |
+-------+-------+------+-------+
| t1    | ID2   |  9   |  97   |
| t3    | ID2   | 15   |  94   |
| t5    | ID2   | 13   | 100   |
+-------+-------+------+-------+

我希望创建一个单一的大数据框,其中包含两个数据框的条目,并使用ffill从前一时间步骤向前填充值。
我可以使用concatsortffill的组合来实现这一点。
但是,首先需要重命名其中一个数据框的列,以避免名称冲突。
df2.columns = [ 'id', 'id2_size', 'id2_price' ]
df = pd.concat([df1, df2]).sort().ffill()

这会导致以下数据框:
        +------+------+-------+----------+-----------+
        | id   | size | price | id2_size | id2_price |
+-------+------+------+-------+----------+-----------+
| time  |      |      |       |          |           |
+-------+------+------+-------+----------+-----------+
| t0    | ID1  | 10   | 110   |     nan  |     nan   |
| t1    | ID2  | 10   | 110   |      9   |      97   |
| t2    | ID1  | 12   | 109   |      9   |      97   |
| t3    | ID2  | 12   | 109   |     15   |      94   |
| t5    | ID2  | 12   | 109   |     13   |     100   |
| t6    | ID1  | 20   | 108   |     13   |     100   |
+-------+------+------+-------+----------+-----------+

我的当前方法相当笨拙,因为我必须重命名其中一个数据框的列。

我认为更好的表示数据的方法是使用多级索引,其中第二维的值来自id列。

生成的数据框将如下所示:

        +--------------+--------------+
        | ID1          | ID2          |
        +------+-------+------+-------+
        | size | price | size | price |
+-------+------+-------+------+-------+
| time  |      |       |      |       |
+-------+------+-------+------+-------+
| t0    | 10   | 110   | nan  | nan   |
| t1    | 10   | 110   |  9   |  97   |
| t2    | 12   | 109   |  9   |  97   |
| t3    | 12   | 109   | 15   |  94   |
| t5    | 12   | 109   | 13   | 100   |
| t6    | 20   | 108   | 13   | 100   |
+-------+------+-------+------+-------+

这是否可能呢?
如果可以的话,从读取的两个csv数据框转到最终合并的多索引数据框需要哪些步骤呢?

1个回答

1
这里有一个一行代码可以实现你所需的功能,虽然在堆栈/反堆栈方面有些复杂。
df1.append(df2).set_index(['time','id']).sort().stack().unstack(level=[1,2]).ffill()

id    ID1        ID2      
     size price size price
time                      
t0     10   110  NaN   NaN
t1     10   110    9    97
t2     12   109    9    97
t3     12   109   15    94
t5     12   109   13   100
t6     20   108   13   100

就我而言,我的默认方法会类似以下内容,这种方法更加简单直接(少了堆叠/解堆)且可以得到相同的基本结果,但是列的组织方式不同:

df1.append(df2).set_index(['time','id']).sort().unstack().ffill()

     size     price     
id    ID1 ID2   ID1  ID2
time                    
t0     10 NaN   110  NaN
t1     10   9   110   97
t2     12   9   109   97
t3     12  15   109   94
t5     12  13   109  100
t6     20  13   108  100

沿着这个思路,您可以添加swaplevelsort,以重新组织列,使其类似于第一种方法:

df1.append(df2).set_index(['time','id']).sort().unstack().ffill().swaplevel(0,1,axis=1).sort(axis=1)

df1.append(df2).set_index(['time','id']) 失败并出现 KeyError: u'no item named time' 错误。我认为这是因为 time 是索引,而 set_index 只考虑列名。如何指定使用现有的索引 time 并包括列 id - Steve Lorimer
诀窍在于使用 append,它将一列添加到现有索引中。df1.append(fd2).set_index('id', append=True) - Steve Lorimer
好的,看起来你已经解决了。我一开始只是在每一个里面使用了默认的[0,1,2,...]索引 -- 所以timeid只是普通列。 你可以通过 reset_index() 来实现它,或者像你做的那样。我通常会在这种情况下先使用 reset_index 再使用 set_index ,这样就能从空白的状态开始建立索引。 - JohnE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接