2017-05-30 70 views
0

假设我有一个数据帧如下,通过一或下一行循环,做计算 - 的Python

ID response time 
1 1315  1.434054 
2 1682  3.753334 
2 2829  5.940094 
3 184  6.243214 
4 243  6.301918 
3 1413  7.486633 
5 2400 11.474644 
6 2151  3.288531 

数据帧有一个ID,响应和时间。

对于没有重复ID(1,4,5,6)的示例,我想返回时间。 对于在ID(2,3)中确实有重复的示例,我想返回min_time列中两次中的最小值和差异列中两次之间的差值。以下是我在看的输出,

ID  response time  min_time  difference 
    1   1315  1.434054 1.434054  NA 
    2   1682  3.753334 3.753334  2.18676 
    2   2829  5.940094 3.753334  2.18676 
    3   184  6.243214 6.243214  1.243419 
    4   243  6.301918 6.301918   NA 
    3   1413  7.486633 6.243214  1.243419 
    5   2400 11.474644 11.474644  NA 
    6   2151  3.288531 3.288531   NA 

虽然我能够把使用循环这个输出,它不是做最好的有效的方法,也需要花费大量的时间。有一个更好的方法吗?

+0

也许这可以帮助:http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.groupby.html – moooeeeep

回答

0

这是一个丑陋的方式,涉及到建立每个ID的最小时间字典。您没有提供解决方案来解决这个问题,所以我很难将它与您所做的相比较,但这并不会太慢。

data = {} 

with open(path) as File: 
    for line in File: 
     ID, response, time = line.split() 
     if ID in data: 
      data[ID].append([response, time]) 
     else: 
      data.update({ID: [[response, time]]}) 

minTimes = {} 
for ID, value in data.items(): 
    if len(value) > 1: 
     for i, j in enumerate(value): 
      if ID in minTimes: 
       if value[i][1] < minTimes[ID]: 
        minTimes[ID] = value[i][1] 
      else: 
       minTimes[ID] = value[i][1] 
    else: 
     minTimes[ID] = 'NA' 

for ID, value in data.items(): 
    for i, j in enumerate(value): 
     if minTimes[ID] != 'NA': 
      value[i] = [ 
          int(value[i][0]), 
          float(value[i][1]), 
          float(minTimes[ID]), 
          abs(float(value[i][1]) - float(minTimes[ID])) 
         ] 
     else: 
      value[i] = [ 
          int(value[i][0]), 
          float(value[i][1]), 
          float(value[i][1]), 
          minTimes[ID] 
         ] 

print(data) 

我会留给你来格式化输出。虽然我正在使用它,但我只是使用json.dumps将它打印得很好,但如果您希望它与您在问题中使用的格式相同,则必须自己执行此操作。

+0

这是不完全是内存优化的解决方案,但它会工作。如果您发现自己在处理更大的数据集,请考虑一下这样的想法:如果您不介意数据的两次传递,则不必每次都存储这些数据,而是每个ID的最短时间。一个收集分钟,一个输出。 – billjamesdev

0

你可以试试这个:

df['min_time'] = df.groupby('ID')['time'].transform(lambda x: x.min()) 

df['difference'] = df.groupby('ID')['time'].transform(lambda x: x.max()-x.min()).replace(0,np.nan) 

print(df) 

输出:

ID response  time min_time difference 
0 1  1315 1.434054 1.434054   NaN 
1 2  1682 3.753334 3.753334 2.186760 
2 2  2829 5.940094 3.753334 2.186760 
3 3  184 6.243214 6.243214 1.243419 
4 4  243 6.301918 6.301918   NaN 
5 3  1413 7.486633 6.243214 1.243419 
6 5  2400 11.474644 11.474644   NaN 
7 6  2151 3.288531 3.288531   NaN 
0

这是你需要什么?也是这旁边,你也可以尝试在transformPandas

funcs = dict(min_time ='min', difference=np.ptp) 
d1 = df.join(df.groupby(['ID']).time.agg(funcs), on=['ID']) 
d1.loc[d1.difference==0]=np.nan 

Out[27]: 
    ID respon  time min_time difference 
0 1.0 1315.0 1.434054 1.434054   NaN 
1 2.0 1682.0 3.753334 3.753334 2.186760 
2 2.0 2829.0 5.940094 3.753334 2.186760 
3 3.0 184.0 6.243214 6.243214 1.243419 
4 4.0 243.0 6.301918 6.301918   NaN 
5 3.0 1413.0 7.486633 6.243214 1.243419 
6 5.0 2400.0 11.474644 11.474644   NaN 
7 6.0 2151.0 3.288531 3.288531   NaN