我的“tidy”格式DataFrame
(列是变量,行是观察值),包含几种不同条件的时间序列数据。我想将数据标准化为每个条件的零小时时间点。
例如,假设我提供了两种不同的animal
两种不同的meal
,然后每小时我记录了剩余的食物数量:
In [4]: df
Out[4]:
animal meal time food_left
0 lion meat 0 10
1 lion meat 1 5
2 lion meat 2 2
3 tiger meat 0 5
4 tiger meat 1 3
5 tiger meat 2 2
6 lion vegetable 0 5
7 lion vegetable 1 5
8 lion vegetable 2 5
9 tiger vegetable 0 5
10 tiger vegetable 1 5
11 tiger vegetable 2 5
对于每个time
点,我想通过从food_eaten
时间点减去food_left
来计算特定动物吃了多少食物(food_left
)点零(对于那种动物和膳食),然后将结果存储在另一列中,例如:
animal meal time food_left food_eaten
0 lion meat 0 10 0
1 lion meat 1 5 5
2 lion meat 2 2 8
3 tiger meat 0 5 0
4 tiger meat 1 3 2
5 tiger meat 2 2 3
6 lion vegetable 0 5 0
7 lion vegetable 1 5 0
8 lion vegetable 2 5 0
9 tiger vegetable 0 5 0
10 tiger vegetable 1 5 0
11 tiger vegetable 2 5 0
我正在努力弄清楚如何在Pandas中应用这种转换来产生最终数据帧(最好也是整齐的格式)。重要的是,我需要保留元数据(animal
,meal
等。)
最好是我想要一个能够推广到不同分组和变换的解决方案;例如,如果我想在每个时间点将老虎吃的量除以狮子在该时间点吃的量(对于给定的一餐),或者找出狮子吃多少的蔬菜而不是肉,以及等等。
我尝试过的事情:
groupby
:
In [15]: df2 = df.set_index(['time'])
In [16]: df2.groupby(['animal','meal']).transform(lambda x: x[0] - x)
Out[16]:
food_left
time
0 0
1 5
2 8
0 0
1 2
2 3
0 0
1 0
2 0
0 0
1 0
2 0
结果是正确的,但元数据已丢失,我无法将其重新加入原始df
如果我在set_index
上['time', 'animal', 'meal']
,那么我就不能groupby
:
In [17]: df2 = df.set_index(['time','animal','meal'])
In [19]: df2.groupby(['animal','meal']).transform(lambda x: x[0] - x)
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
... snip ...
KeyError: 'animal'
pivot
:
In [21]: data_pivot = df.pivot_table(columns=['animal','meal'],index=['time'],values='food_left')
In [22]: data_norm = data_pivot.rsub(data_pivot.loc[0], axis=1)
In [23]: data_norm
Out[23]:
animal lion tiger
meal meat vegetable meat vegetable
time
0 0 0 0 0
1 5 0 2 0
2 8 0 3 0
这有点好,我可以用melt
或unstack
检索原始数据,但看起来不太优雅。有没有更好的办法?
答案 0 :(得分:1)
您可以根据转换的数据创建一个新列,作为一行,它将是:
df['food_eaten'] = df.set_index(['time']).groupby(['animal', 'meal']).
transform(lambda x: x[0] - x).values
DF
animal meal time food_left food_eaten
0 lion meat 0 10 0
1 lion meat 1 5 5
2 lion meat 2 2 8
3 tiger meat 0 5 0
4 tiger meat 1 3 2
5 tiger meat 2 2 3
6 lion vegetable 0 5 0
7 lion vegetable 1 5 0
8 lion vegetable 2 5 0
9 tiger vegetable 0 5 0
10 tiger vegetable 1 5 0
11 tiger vegetable 2 5 0
答案 1 :(得分:0)
您想使用groupby
和diff
:
df['food_eaten'] = -df.groupby(['animal', 'meal'])['food_left'].diff()
如果您想要零而不是NaN,那么请使用fillna(),以免出现任何情况。虽然这并没有直接推广,但现在每个时间间隔内每只动物吃掉的每种食物的数量都是一样的,所以你可以在这个新的领域进行额外的计算。