Python 按标签将多索引数据帧分组以计算平均值

Python 按标签将多索引数据帧分组以计算平均值,python,pandas,pandas-groupby,Python,Pandas,Pandas Groupby,我有一个生成.csv文件的随机算法。这些文件的内容如下所示: module, coverage, timestamp examples.monkey, 32.142857142857146, 1546513589.59586 examples.monkey, 35.714285714285715, 1546513589.609822 examples.monkey, 35.714285714285715, 1546513589.617172 ... util.container, 27.5862

我有一个生成.csv文件的随机算法。这些文件的内容如下所示:

module, coverage, timestamp
examples.monkey, 32.142857142857146, 1546513589.59586
examples.monkey, 35.714285714285715, 1546513589.609822
examples.monkey, 35.714285714285715, 1546513589.617172
...
util.container, 27.586206896551722 ,1546513594.559889
util.container, 27.586206896551722 ,1546513594.579989
util.container, 27.586206896551722 ,1546513594.598491
             Run 0                 ...           Run 4              
            module   coverage      ...        coverage     timestamp
0  examples.monkey  32.142857      ...       32.142857  1.546514e+09
1  examples.monkey  35.714286      ...       32.142857  1.546514e+09
2  examples.monkey  35.714286      ...       32.142857  1.546514e+09
3  examples.monkey  35.714286      ...       35.714286  1.546514e+09
4  examples.monkey  35.714286      ...       35.714286  1.546514e+09
我有30到100个这样的文件,平均长度为几千行

我的最终目标是为每个测量绘制一个图表,并绘制一个额外的图表,描述给定时间所有测量的平均值。 为此,我需要计算每个时间戳的所有运行的平均值。 (当然,如果文件没有某个时间戳的条目,我只会忽略它。)

到目前为止,我读取了所有的.csv文件,并将它们连接到一个新的数据帧中

allFiles = glob.glob("out/*.csv")
dfs = []

for file_ in allFiles:
    df = pd.read_csv(file_, index_col=None, header=0)
    dfs.append(df)

keys = ["Run " + str(i) for i in range(len(dfs))]
glued = pd.concat(dfs, axis=1, keys=keys)
这将产生如下所示的数据帧:

module, coverage, timestamp
examples.monkey, 32.142857142857146, 1546513589.59586
examples.monkey, 35.714285714285715, 1546513589.609822
examples.monkey, 35.714285714285715, 1546513589.617172
...
util.container, 27.586206896551722 ,1546513594.559889
util.container, 27.586206896551722 ,1546513594.579989
util.container, 27.586206896551722 ,1546513594.598491
             Run 0                 ...           Run 4              
            module   coverage      ...        coverage     timestamp
0  examples.monkey  32.142857      ...       32.142857  1.546514e+09
1  examples.monkey  35.714286      ...       32.142857  1.546514e+09
2  examples.monkey  35.714286      ...       32.142857  1.546514e+09
3  examples.monkey  35.714286      ...       35.714286  1.546514e+09
4  examples.monkey  35.714286      ...       35.714286  1.546514e+09
现在,我最初的想法是简单地跨所有运行进行分组,按照模块和时间戳在级别=1、跨轴=1进行分组。像这样

grouped = glued.groupby(by=["module", "timestamp"], level=1, axis=1)
然而,这不起作用,因为我得到了一个Keyerror,表示模块和时间戳丢失。显然,我对如何使用这样的组合数据帧有一些误解


那么,我如何才能最好地获得每个模块的平均覆盖率和跨多个文件的时间戳呢?

我不确定您的答案为什么不起作用,我对“多级”专栏中的groubpy不太熟悉。我可以提出一个可行的答案。正如@jezrael在他的评论中指出的,您可以通过添加新的列而不是在行上连接来连接数据帧。如果您这样做:

glued = pd.concat(dfs)
grouped = glued.groupby(["module", "timestamp"])
mean_by_group = grouped.mean() 
mean_by_group应该是一个数据帧,每个模块/时间戳对有一行,一列包含对应于该时间戳/模块对的所有条目的覆盖率平均值。

您可以使用by
axis=0
什么是默认参数,因此应该删除,然后将第一级转换为列
Run
并聚合
mean

allFiles = glob.glob("out/*.csv")

#instead loop list comprehension, but your solution working nice too
dfs = [pd.read_csv(fp,skipinitialspace=True) for fp in allFiles]
keys = ["Run " + str(i) for i in range(len(dfs))]

glued = pd.concat(dfs, keys=keys).reset_index(level=0).rename(columns={'level_0':'Run'})
#convert float column to datetimes 
glued['timestamp'] = pd.to_datetime(glued['timestamp'], unit='s')
#print (glued)

#specify columns what need 
grouped = glued.groupby(by=["Run","module", "timestamp"], as_index=False).mean()
#print (grouped)

grouped1 = glued.groupby(by=["module", "timestamp"], as_index=False).mean()
#print (grouped1)

对于最后的
3
column数据帧,如果每个文件中的列名相同,则不使用
glued=pd.concat(dfs,axis=0,keys=keys)
是有原因的。Sry,我的代码中漏了一行。我提供键作为分隔它们的另一个索引。我编辑了我的问题。我的方法基于这里的答案是的,
是个好主意。但我认为concat是通过
axis=0
,而不是通过
axis=1
。你有可能吗?在每个文件中都有相同的列名称?是的,我使用哪个轴应该无关紧要,我想我可以随时转换。这些文件在列方面是相同的,只是条目可能不同。我仍然不确定,当我处理行而不是列时,为什么它会起作用,但结果正是我所需要的。您能详细解释一下为什么会有这种差异吗?@FChris-存在差异,因为不可能添加列名,只能按所有级别进行分组,如
.groupby(level=1,axis=1).mean()
,但不起作用,因为需要所有数字列。因此,如果使用
grouped=glued.loc[:,pd.indexlice[:,['coverage']]]].groupby(level=1,axis=1).mean()
首先选择所有
coverage
级别,然后聚合
mean
。但是这里不可能指定
模块
。我明白了,非常感谢您的额外解释。如果使用
glued=pd.concat(dfs,keys=keys)
那么
grouped=glued.groupby(by=[“module”,“timestamp”],level=1,axis=1)
与您希望按
运行0
运行1进行分组一样