为什么当我应用 DataFrame.sub() 时我得到了具有更多列的新 DF?
Why when I apply DataFrame.sub() I get the new DF with a higher number of columns?
当我在这种特定情况下应用 .sub()
方法时,我无法理解 Pandas
的行为,我的目标是将 DataFrame
中的行居中。
基本上我想为每一行计算平均值,然后从每一行中减去该值以使 DataFrame
居中。
我认为这个问题可能与元素操作有关,但在阅读文档后仍然很模糊,原因也很模糊 here
import pandas as pd
val = {1: [1,2,3,4],
2: [4,5,6,7],
3: [8,9,10,11],
4: [12,13,14,15]}
df = pd.DataFrame(val)
# Computing for each row the mean value
avg = df.mean(axis=1)
#Removing the mean value from each element in each row
df_centered = df.sub(avg,axis=1)
print(df)
print(avg)
print(df_centered)
1 2 3 4
0 1 4 8 12
1 2 5 9 13
2 3 6 10 14
3 4 7 11 15
0 6.25
1 7.25
2 8.25
3 9.25
dtype: float64
0 1 2 3 4
0 NaN -6.25 -4.25 -1.25 NaN
1 NaN -5.25 -3.25 -0.25 NaN
2 NaN -4.25 -2.25 0.75 NaN
3 NaN -3.25 -1.25 1.75 NaN
- 我不明白为什么我得到这个输出
- 我希望我的输出是 4X4 而不是 4X5,为什么我有第 5 列?
- 为什么我从操作中得到
NaN
?
编辑
预期输出:
df_centered
1 2 3 4
0 -5.25 -2.25 1.75 5.75
1 -5.25 -2.25 1.75 5.75
2 -5.25 -2.25 1.75 5.75
3 -5.25 -2.25 1.75 5.75
我认为所有行都相等这一事实仅适用于此示例。
现在,如果您从 df_centered
计算每一行的平均值,它将是 0
,正如“居中”过程所预期的那样。
在DataFrame.sub
中使用axis=0
来减去前行,这意味着6.25
被DataFrame的第一行减去:
df_centered = df.sub(avg,axis=0)
print(df_centered)
1 2 3 4
0 -5.25 -2.25 1.75 5.75
1 -5.25 -2.25 1.75 5.75
2 -5.25 -2.25 1.75 5.75
3 -5.25 -2.25 1.75 5.75
Why I get NaN from the operation?
因为列 0,5
的索引与 Series
avg
的索引不同,这里是 1,2,3,4
,所以 pandas 不匹配并且缺少列已创建。
您所有问题的答案都在这部分文档中:
For Series input, axis to match Series index on.
在您的情况下,您的列是 print(df.columns)
:
Int64Index([1, 2, 3, 4], dtype='int64')
同时 print(avg)
:
0 6.25
1 7.25
2 8.25
3 9.25
dtype: float64
所以这里的索引是 0, 1, 2, 3
.
根据上面的文档,您需要向 df
添加一个额外的列 0
,同样地 avg
中没有索引 4
所以你用 NaN 做减法,结果是 NaN。
克服这个问题的一种方法是将 avg
中的索引重命名为
avg.index = df.columns
但是,据我所知,使用 level=0
或 level=1
会产生相同的结果。
估计是广播操作的方式有问题。所以我建议您采用以下解决方案。
数据
import numpy as np
import pandas as pd
import pandas as pd
val = {1: [1,2,3,4],
2: [4,5,6,7],
3: [8,9,10,11],
4: [12,13,14,15]}
df = pd.DataFrame(val)
生成要减去的矩阵
我们首先要求结果是一个numpy数组
avg = df.mean(axis=1).values
然后我们重复 df
中的行数
rep = np.repeat(avg, len(df))
最后我们根据df
重塑它
mat = rep.reshape(df.shape)
[[6.25 6.25 6.25 6.25]
[7.25 7.25 7.25 7.25]
[8.25 8.25 8.25 8.25]
[9.25 9.25 9.25 9.25]]
现在 df.sub
按预期工作
df_centered = df.sub(mat)
您要查找的数据框是哪个
1 2 3 4
0 -5.25 -2.25 1.75 5.75
1 -5.25 -2.25 1.75 5.75
2 -5.25 -2.25 1.75 5.75
3 -5.25 -2.25 1.75 5.75
当我在这种特定情况下应用 .sub()
方法时,我无法理解 Pandas
的行为,我的目标是将 DataFrame
中的行居中。
基本上我想为每一行计算平均值,然后从每一行中减去该值以使 DataFrame
居中。
我认为这个问题可能与元素操作有关,但在阅读文档后仍然很模糊,原因也很模糊 here
import pandas as pd
val = {1: [1,2,3,4],
2: [4,5,6,7],
3: [8,9,10,11],
4: [12,13,14,15]}
df = pd.DataFrame(val)
# Computing for each row the mean value
avg = df.mean(axis=1)
#Removing the mean value from each element in each row
df_centered = df.sub(avg,axis=1)
print(df)
print(avg)
print(df_centered)
1 2 3 4
0 1 4 8 12
1 2 5 9 13
2 3 6 10 14
3 4 7 11 15
0 6.25
1 7.25
2 8.25
3 9.25
dtype: float64
0 1 2 3 4
0 NaN -6.25 -4.25 -1.25 NaN
1 NaN -5.25 -3.25 -0.25 NaN
2 NaN -4.25 -2.25 0.75 NaN
3 NaN -3.25 -1.25 1.75 NaN
- 我不明白为什么我得到这个输出
- 我希望我的输出是 4X4 而不是 4X5,为什么我有第 5 列?
- 为什么我从操作中得到
NaN
?
编辑
预期输出:
df_centered
1 2 3 4
0 -5.25 -2.25 1.75 5.75
1 -5.25 -2.25 1.75 5.75
2 -5.25 -2.25 1.75 5.75
3 -5.25 -2.25 1.75 5.75
我认为所有行都相等这一事实仅适用于此示例。
现在,如果您从 df_centered
计算每一行的平均值,它将是 0
,正如“居中”过程所预期的那样。
在DataFrame.sub
中使用axis=0
来减去前行,这意味着6.25
被DataFrame的第一行减去:
df_centered = df.sub(avg,axis=0)
print(df_centered)
1 2 3 4
0 -5.25 -2.25 1.75 5.75
1 -5.25 -2.25 1.75 5.75
2 -5.25 -2.25 1.75 5.75
3 -5.25 -2.25 1.75 5.75
Why I get NaN from the operation?
因为列 0,5
的索引与 Series
avg
的索引不同,这里是 1,2,3,4
,所以 pandas 不匹配并且缺少列已创建。
您所有问题的答案都在这部分文档中:
For Series input, axis to match Series index on.
在您的情况下,您的列是 print(df.columns)
:
Int64Index([1, 2, 3, 4], dtype='int64')
同时 print(avg)
:
0 6.25
1 7.25
2 8.25
3 9.25
dtype: float64
所以这里的索引是 0, 1, 2, 3
.
根据上面的文档,您需要向 df
添加一个额外的列 0
,同样地 avg
中没有索引 4
所以你用 NaN 做减法,结果是 NaN。
克服这个问题的一种方法是将 avg
中的索引重命名为
avg.index = df.columns
但是,据我所知,使用 level=0
或 level=1
会产生相同的结果。
估计是广播操作的方式有问题。所以我建议您采用以下解决方案。
数据
import numpy as np
import pandas as pd
import pandas as pd
val = {1: [1,2,3,4],
2: [4,5,6,7],
3: [8,9,10,11],
4: [12,13,14,15]}
df = pd.DataFrame(val)
生成要减去的矩阵
我们首先要求结果是一个numpy数组
avg = df.mean(axis=1).values
然后我们重复 df
rep = np.repeat(avg, len(df))
最后我们根据df
mat = rep.reshape(df.shape)
[[6.25 6.25 6.25 6.25]
[7.25 7.25 7.25 7.25]
[8.25 8.25 8.25 8.25]
[9.25 9.25 9.25 9.25]]
现在 df.sub
按预期工作
df_centered = df.sub(mat)
您要查找的数据框是哪个
1 2 3 4
0 -5.25 -2.25 1.75 5.75
1 -5.25 -2.25 1.75 5.75
2 -5.25 -2.25 1.75 5.75
3 -5.25 -2.25 1.75 5.75