【发布时间】:2014-11-22 17:57:18
【问题描述】:
我有一个数据框,其中的行按化学元素类型索引,列代表不同的样本。这些值是浮点数,表示每个样本中行元素的存在程度。
我想计算每一行的平均值,然后从该特定行中的每个值中减去它以标准化数据,并为该数据集创建一个新的数据框。
我尝试使用 mean(1),它为我提供了一个 Series 对象,其中包含每个化学元素的平均值,这很好,但后来我尝试使用减法,但没有用。
【问题讨论】:
我有一个数据框,其中的行按化学元素类型索引,列代表不同的样本。这些值是浮点数,表示每个样本中行元素的存在程度。
我想计算每一行的平均值,然后从该特定行中的每个值中减去它以标准化数据,并为该数据集创建一个新的数据框。
我尝试使用 mean(1),它为我提供了一个 Series 对象,其中包含每个化学元素的平均值,这很好,但后来我尝试使用减法,但没有用。
【问题讨论】:
您可以使用 DataFrame 的 sub 方法并指定减法应该按行 (axis=0) 发生,而不是默认的按列行为:
df.sub(df.mean(axis=1), axis=0)
这是一个例子:
>>> df = pd.DataFrame({'a': [1.5, 2.5], 'b': [0.25, 2.75], 'c': [1.25, 0.75]})
>>> df
a b c
0 1.5 0.25 1.25
1 2.5 2.75 0.75
每一行的平均值很容易计算:
>>> df.mean(axis=1)
0 1
1 2
dtype: float64
要对 DataFrame 的行进行去均值,只需从 df 中减去行的平均值,如下所示:
>>> df.sub(df.mean(axis=1), axis=0)
a b c
0 0.5 -0.75 0.25
1 0.5 0.75 -1.25
【讨论】:
axis=1 表示逐行平均,但是,axis=1 表示逐列减去,我是否误解了传统如何使用轴?
axis=1 只是意味着“跨越数据帧”。这可能意味着一行中的条目(如df.mean(axis=1)),或者,由于列的名称也跨越DataFrame,当需要引用列名时使用axis=1。我认为 Stack Overflow 上有几个关于这个主题的问题,我回答了其中一个问题here。
除了@ajcr 的出色回答之外,您可能还需要考虑重新安排存储数据的方式。
您目前的操作方式(不同列中的不同样本)是您使用电子表格时的表示方式,但这可能不是表示数据的最有用方式。
通常,每一列代表关于单个现实世界实体的唯一信息。这类数据的典型例子是人:
id name hair_colour Age
1 Bob Brown 25
真的,您的不同样本是不同的现实世界实体。
因此,我建议使用两级索引来描述每条信息。这使得以您想要的方式操作数据更加方便。
因此:
>>> df = pd.DataFrame([['Sn',1,2,3],['Pb',2,4,6]],
columns=['element', 'A', 'B', 'C']).set_index('element')
>>> df.columns.name = 'sample'
>>> df # This is how your DataFrame looks at the moment
sample A B C
element
Sn 1 2 3
Pb 2 4 6
>>> # Now make those columns into a second level of index
>>> df = df.stack()
>>> df
element sample
Sn A 1
B 2
C 3
Pb A 2
B 4
C 6
我们现在可以使用groupby 的所有美味功能:
>>> demean = lambda x: x - x.mean()
>>> df.groupby(level='element').transform(demean)
element sample
Sn A -1
B 0
C 1
Pb A -2
B 0
C 2
当您以这种方式查看数据时,您会发现很多很多以前是多列的用例 DataFrames 实际上是 MultiIndexed Series,并且您对数据的处理方式拥有更多的权力被表示和转换。
【讨论】: