我有一个pandas数据帧:
a = pd.DataFrame(rand(5,6)*10, index=pd.DatetimeIndex(start='2005', periods=5, freq='A'))
a.columns = pd.MultiIndex.from_product([('A','B'),('a','b','c')])
我想从a['2005']
中减去行a
。为此,我尝试过这个:
In [22]:
a - a.ix['2005']
Out[22]:
A B
a b c a b c
2005-12-31 0 0 0 0 0 0
2006-12-31 NaN NaN NaN NaN NaN NaN
2007-12-31 NaN NaN NaN NaN NaN NaN
2008-12-31 NaN NaN NaN NaN NaN NaN
2009-12-31 NaN NaN NaN NaN NaN NaN
这显然不起作用,因为在进行操作时,大熊猫正在排列索引。这有效:
In [24]:
pd.DataFrame(a.values - a['2005'].values, index=a.index, columns=a.columns)
Out[24]:
A B
a b c a b c
2005-12-31 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
2006-12-31 -3.326761 -7.164628 8.188518 -0.863177 0.519587 -3.281982
2007-12-31 3.529531 -4.719756 8.444488 1.355366 7.468361 -4.023797
2008-12-31 3.139185 -8.420257 1.465101 -2.942519 1.219060 -5.146019
2009-12-31 -3.459710 0.519435 -1.049617 -2.779370 4.792227 -1.922461
但是,每次我必须执行此类操作时,我都不想构建新的DataFrame。我尝试过这样的apply()方法:a.apply(lambda x: x-a['2005'].values)
但我得到ValueError: cannot copy sequence with size 6 to array axis with dimension 5
所以我不确定如何继续。有没有一种简单的方法可以做到这一点,我没有看到?我认为应该有一个简单的方法来实现这一点,因此您不必每次都构建一个新的数据帧。我也尝试了sub()
方法,但减法仅应用于第一行,而我想从数据帧中的每一行中减去第一行。
答案 0 :(得分:7)
Pandas很适合按索引排列。因此,当您希望Pandas忽略索引时,您需要删除索引。您可以通过将DataFrame a.loc['2005']
转换为1维NumPy数组来实现这一目标:
In [56]: a - a.loc['2005'].values.squeeze()
Out[56]:
A B
a b c a b c
2005-12-31 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
2006-12-31 0.325968 1.314776 -0.789328 -0.344669 -2.518857 7.361711
2007-12-31 0.084203 2.234445 -2.838454 -6.176795 -3.645513 8.955443
2008-12-31 3.798700 0.299529 1.303325 -2.770126 -1.284188 3.093806
2009-12-31 1.520930 2.660040 0.846996 -9.437851 -2.886603 6.705391
squeeze
method将形状为a.loc['2005']
的NumPy数组(1, 6)
转换为形状(6,)
的数组。这允许根据需要广播阵列(在减法期间)。
答案 1 :(得分:2)
这是一个更详细的简单分解如何做到这一点。
首先制作一个简单的DataFrame,以便于理解。
import numpy as np
import pandas as pd
#make a simple DataFrame
df = pd.DataFrame(np.fromfunction(lambda i, j: i+1 , (3, 3), dtype=int))
这将是这样的
# 1 1 1
# 2 2 2
# 3 3 3
现在从第一行获取值
first_row = df.iloc[[0]].values[0]
现在使用apply()从其余行中减去第一行。
df.apply(lambda row: row - first_row, axis=1)
结果将如下所示。看到每行减去1
# 0 0 0
# 1 1 1
# 2 2 2
答案 2 :(得分:2)
要使用时间戳值来计算相对于开始时间经过的时间,请使用:
df['Time_column'].apply(lambda x: x-df.iloc[[0],[1]])
df.iloc[[0],[1]]
=开始时间