跨多个唯一行计算结果

时间:2019-03-14 06:37:56

标签: python pandas

我有以下MVCE:

import pandas as pd

data_in = [
  { 'foo': 'company A', 'bar': 'division 1', 'time': 1, 'diff': 0.99 },
  { 'foo': 'company A', 'bar': 'division 1', 'time': 2, 'diff': 0.95 },
  { 'foo': 'company A', 'bar': 'division 1', 'time': 3, 'diff': 0.94 },
  { 'foo': 'company A', 'bar': 'division 1', 'time': 4, 'diff': 0.90 },
  { 'foo': 'company A', 'bar': 'division 1', 'time': 5, 'diff': 1.01 },

  { 'foo': 'company A', 'bar': 'division 2', 'time': 1, 'diff': 0.91 },
  { 'foo': 'company A', 'bar': 'division 2', 'time': 2, 'diff': 0.92 },
  { 'foo': 'company A', 'bar': 'division 2', 'time': 3, 'diff': 0.93 },
  { 'foo': 'company A', 'bar': 'division 2', 'time': 4, 'diff': 0.94 },
  { 'foo': 'company A', 'bar': 'division 2', 'time': 5, 'diff': 0.95 },

  { 'foo': 'company B', 'bar': 'division 1', 'time': 1, 'diff': 1.01 },
  { 'foo': 'company B', 'bar': 'division 1', 'time': 2, 'diff': 1.08 },
  { 'foo': 'company B', 'bar': 'division 1', 'time': 3, 'diff': 1.21 },
  { 'foo': 'company B', 'bar': 'division 1', 'time': 4, 'diff': 1.22 },
  { 'foo': 'company B', 'bar': 'division 1', 'time': 5, 'diff': 1.18 },

  { 'foo': 'company B', 'bar': 'division 2', 'time': 1, 'diff': 0.81 },
  { 'foo': 'company B', 'bar': 'division 2', 'time': 2, 'diff': 0.82 },
  { 'foo': 'company B', 'bar': 'division 2', 'time': 3, 'diff': 0.88 },
  { 'foo': 'company B', 'bar': 'division 2', 'time': 4, 'diff': 0.87 },
  { 'foo': 'company B', 'bar': 'division 2', 'time': 5, 'diff': 0.87 },
]

df = pd.DataFrame(data_in).set_index(['foo', 'bar', 'time'])
df.sort_index(axis=0, inplace=True)

data_out = []
for name, group in df.groupby(['foo', 'time']):

  print(group) 
# example output
# foo       bar        time
# company B division 1 5     1.18
#           division 2 5     0.87
  result = '?'
  data_out.append({ 'foo': name[0], 'time': name[1], 'result': result })

print('out', data_out)

本质上,每次尝试记录diff时,我都试图通过比较两个部门来为每个公司计算一些结果。

例如,我试图得出一个真实的结果,即“目标1”在目标指标之上执行,而“目标2”在标准目标之下执行时。

我发现的一种可能的解决方案是

for name, group in df.groupby(['foo', 'time']):
  group = group.reset_index()

  group.loc[(group['bar'] =="division 1") & (group['diff'] > 1.04), 'result'] = True
  group.loc[(group['bar'] =="division 2") & (group['diff'] < 1), 'result'] = True
  group['result'] = group['result'].fillna(False)
  result = group['result'].all(skipna=False)

但是每个结果可能有数百个数据点,我觉得这种解决方案将很快使数百或数千个其他列的数据帧膨胀。

我可能需要直接比较两行之间的diff(即,如果“部门1”小于“部门2”),我无法弄清楚如何使用上述解决方案。

由于要处理的数据量大,我主要担心速度,但也希望避免不必要的内存使用。

进行此类计算的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

旋转在这里可能是一种不错的方法:

df.pivot_table(index=['foo', 'time'], columns='bar', values='diff')

给予:

bar             division 1  division 2
foo       time                        
company A 1           0.99        0.91
          2           0.95        0.92
          3           0.94        0.93
          4           0.90        0.94
          5           1.01        0.95
company B 1           1.01        0.81
          2           1.08        0.82
          3           1.21        0.88
          4           1.22        0.87
          5           1.18        0.87

您现在可以在列中获得分度的值,这将使比较更加容易。


我也可以尝试unstack。它的通用性较差,但可以使用时效率更高。在我的测试中,速度快了7倍以上:

df.unstack(1)
                     diff           
bar            division 1 division 2
foo       time                      
company A 1          0.99       0.91
          2          0.95       0.92
          3          0.94       0.93
          4          0.90       0.94
          5          1.01       0.95
company B 1          1.01       0.81
          2          1.08       0.82
          3          1.21       0.88
          4          1.22       0.87
          5          1.18       0.87