Python 计算表中每x行的平均值并创建新表
我有一个很长的数据表(约200行50列),我需要创建一个代码,可以计算表中每两行和每列的平均值,最终输出是一个新的平均值表。在Excel中这样做显然是疯狂的!我使用python3,我知道一些类似的问题:,和。但这些都没有帮助,因为我需要一些优雅的代码来处理多个列并生成一个有组织的数据表。顺便说一句,我的原始数据表是使用pandas导入的,它被定义为数据帧,但在pandas中找不到一种简单的方法来实现这一点。非常感谢你的帮助 该表的一个示例(简短版本)为: 预期平均值表:Python 计算表中每x行的平均值并创建新表,python,python-3.x,pandas,dataframe,numpy,Python,Python 3.x,Pandas,Dataframe,Numpy,我有一个很长的数据表(约200行50列),我需要创建一个代码,可以计算表中每两行和每列的平均值,最终输出是一个新的平均值表。在Excel中这样做显然是疯狂的!我使用python3,我知道一些类似的问题:,和。但这些都没有帮助,因为我需要一些优雅的代码来处理多个列并生成一个有组织的数据表。顺便说一句,我的原始数据表是使用pandas导入的,它被定义为数据帧,但在pandas中找不到一种简单的方法来实现这一点。非常感谢你的帮助 该表的一个示例(简短版本)为: 预期平均值表: a b c
a b c d
3 30.5 31.5 35
7 35 21.5 25
11 37.5 41.5 38.5
15 10 16 18.5
19 15.5 27 38
您可以使用
df.index//2
(或者如@DSM所指出的,使用np.arange(len(df))//2
-创建一个人工组,以便它适用于所有索引),然后使用groupby:
df.groupby(np.arange(len(df))//2).mean()
Out[13]:
a b c d
0 3.0 30.5 31.5 35.0
1 7.0 35.0 21.5 25.0
2 11.0 37.5 41.5 38.5
3 15.0 10.0 16.0 18.5
4 19.0 15.5 27.0 38.0
NumPythonic方法是将元素提取为具有
df.值的NumPy数组,然后沿着axis=1
和axis=2
执行axis=1
的2
元素重塑为3D
数组,最后转换回数据帧,像这样-
pd.DataFrame(df.values.reshape(-1,2,df.shape[1]).mean(1))
pd.DataFrame(np.einsum('ijk->ik',df.values.reshape(-1,2,df.shape[1]))/2.0)
事实证明,您可以引入NumPy非常有效的工具:将平均缩减
作为总和缩减
和缩小
的组合,如下所示-
pd.DataFrame(df.values.reshape(-1,2,df.shape[1]).mean(1))
pd.DataFrame(np.einsum('ijk->ik',df.values.reshape(-1,2,df.shape[1]))/2.0)
请注意,建议的方法假设行数可被2
整除
同样,为了保留列名,您需要在转换回数据帧时添加columns=df.columns
,即-
pd.DataFrame(...,columns=df.columns)
样本运行-
>>> df
0 1 2 3
0 2 50 25 26
1 4 11 38 44
2 6 33 16 25
3 8 37 27 25
4 10 28 48 32
5 12 47 35 45
6 14 8 16 7
7 16 12 16 30
8 18 22 39 29
9 20 9 15 47
>>> pd.DataFrame(df.values.reshape(-1,2,df.shape[1]).mean(1))
0 1 2 3
0 3 30.5 31.5 35.0
1 7 35.0 21.5 25.0
2 11 37.5 41.5 38.5
3 15 10.0 16.0 18.5
4 19 15.5 27.0 38.0
>>> pd.DataFrame(np.einsum('ijk->ik',df.values.reshape(-1,2,df.shape[1]))/2.0)
0 1 2 3
0 3 30.5 31.5 35.0
1 7 35.0 21.5 25.0
2 11 37.5 41.5 38.5
3 15 10.0 16.0 18.5
4 19 15.5 27.0 38.0
运行时测试-
在本节中,让我们测试迄今为止列出的解决性能问题的所有三种方法,包括
您可以使用pd.rolling()
来解决这个问题,创建滚动平均值,然后使用iloc
df = df.rolling(2).mean()
df = df.iloc[::2, :]
请注意,第一个观察结果将丢失(即滚动从顶部开始),因此请确保检查您的数据是否按您需要的方式进行排序。在您的情况下,假设您的dataframe名称为new
new = new.groupby(np.arange(len(new)) // 2).mean()
如果要对列进行平均
new = new.groupby(np.arrange(len(new.columns)) // 2, axis=1).mean()
当我尝试使用numpy
创建人工组时,我得到了ValueError:Grouper和axis的长度必须相同。或者,您可以使用itertools
,它将生成与数据帧长度相等的迭代器:
SAMPLE_SIZE = 2
label_series = pd.Series(itertools.chain.from_iterable(itertools.repeat(x, SAMPLE_SIZE) for x in df.index))
sampled_df = df.groupby(label_series).mean()
我在[这里]找到了一些相似的东西(stackoverflow.com/questions/36810595/calculate-average-of-every-x-rows-in-a-table-and-create-new-table),但你的答案非常优雅简洁。非常感谢你!出于兴趣,df.index//2中的第一个正斜杠是什么意思?不客气。也就是整数除法,所以2//2和3//2都产生1,4//2和5//2产生2。。。(并放入同一组)明白了!谢谢!如果索引不是简单的0,1,2,那么最好改为在np.arange(len(df))//2上分组。。稍快一点的是df.groupby(np.arange(len(df.index))//2.mean()
;)这个比groupby快约2倍。不错。@ayhan是的,我注意到了,我正要发布运行时,但最后的想法是让它过去:)你的是我学到的新东西,熊猫不是我的东西!请注意,numpy方法会丢失列名。您可以添加columns=df.columns
来更正此问题。@DSM是的,完全没有注意到!谢谢作为一个注释补充。这比以前的答案要优雅得多。
SAMPLE_SIZE = 2
label_series = pd.Series(itertools.chain.from_iterable(itertools.repeat(x, SAMPLE_SIZE) for x in df.index))
sampled_df = df.groupby(label_series).mean()