首页 文章

Pandas groupby对象被记住多久了?

提问于
浏览
0

我有以下Python 3.4脚本示例 . 它执行以下操作:

  • 创建一个数据框,

  • 将日期变量转换为datetime64格式,

  • 根据两个分类变量创建一个groupby对象,

  • 生成一个数据框,其中包含每个组中数字项的计数,

  • 将计数数据帧与原始数据帧合并,以创建包含每个组中行数的列

  • 创建一个包含连续行之间日期差异的列 .

这是脚本:

import numpy as np
import pandas as pd

# Create dataframe consisting of id, date and two categories (gender and age)
tempDF = pd.DataFrame({ 'id': [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],
                        'date': ["02/04/2015 02:34","06/04/2015 12:34","09/04/2015 23:03","12/04/2015 01:00","15/04/2015 07:12","21/04/2015 12:59","29/04/2015 17:33","04/05/2015 10:44","06/05/2015 11:12","10/05/2015 08:52","12/05/2015 14:19","19/05/2015 19:22","27/05/2015 22:31","01/06/2015 11:09","04/06/2015 12:57","10/06/2015 04:00","15/06/2015 03:23","19/06/2015 05:37","23/06/2015 13:41","27/06/2015 15:43"],
                        'gender': ["male","female","female","male","male","female","female",np.nan,"male","male","female","male","female","female","male","female","male","female",np.nan,"male"],
                        'age': ["young","old","old","old","old","old",np.nan,"old","old","young","young","old","young","young","old",np.nan,"old","young",np.nan,np.nan]})

# Convert date to datetime
tempDF['date'] = pd.to_datetime(tempDF['date'])

# Create groupby object based on two categorical variables
tempGroupby = tempDF.sort_values(['gender','age','id']).groupby(['gender','age'])

# Count number in each group and merge with original dataframe to create 'count' column
tempCountsDF = tempGroupby['id'].count().reset_index(drop=False)
tempCountsDF = tempCountsDF.rename(columns={'id': 'count'})
tempDF = tempDF.merge(tempCountsDF, on=['gender','age'])

# Calculate difference between consecutive rows in each group. (First row in each
# group should have date difference = NaT)
tempGroupby = tempDF.sort_values(['gender','age','id']).groupby(['gender','age'])
tempDF['diff'] = tempGroupby['date'].diff()
print(tempDF)

此脚本生成以下输出:

age                date  gender  id  count                diff
0   young 2015-02-04 02:34:00    male   1      2                 NaT
1   young 2015-10-05 08:52:00    male  10      2   243 days 06:18:00
2     old 2015-06-04 12:34:00  female   2      3                 NaT
3     old 2015-09-04 23:03:00  female   3      3    92 days 10:29:00
4     old 2015-04-21 12:59:00  female   6      3 -137 days +13:56:00
5     old 2015-12-04 01:00:00    male   4      6                 NaT
6     old 2015-04-15 07:12:00    male   5      6 -233 days +06:12:00
7     old 2015-06-05 11:12:00    male   9      6    51 days 04:00:00
8     old 2015-05-19 19:22:00    male  12      6  -17 days +08:10:00
9     old 2015-04-06 12:57:00    male  15      6  -44 days +17:35:00
10    old 2015-06-15 03:23:00    male  17      6    69 days 14:26:00
11  young 2015-12-05 14:19:00  female  11      4                 NaT
12  young 2015-05-27 22:31:00  female  13      4 -192 days +08:12:00
13  young 2015-01-06 11:09:00  female  14      4 -142 days +12:38:00
14  young 2015-06-19 05:37:00  female  18      4   163 days 18:28:00

而这正是我所期待的 . 但是,它似乎依赖于两次创建groupby对象(以完全相同的方式) . 如果第二个groupby定义被注释掉,它似乎导致diff列中的输出非常不同:

import numpy as np
import pandas as pd

# Create dataframe consisting of id, date and two categories (gender and age)
tempDF = pd.DataFrame({ 'id': [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20],
                        'date': ["02/04/2015 02:34","06/04/2015 12:34","09/04/2015 23:03","12/04/2015 01:00","15/04/2015 07:12","21/04/2015 12:59","29/04/2015 17:33","04/05/2015 10:44","06/05/2015 11:12","10/05/2015 08:52","12/05/2015 14:19","19/05/2015 19:22","27/05/2015 22:31","01/06/2015 11:09","04/06/2015 12:57","10/06/2015 04:00","15/06/2015 03:23","19/06/2015 05:37","23/06/2015 13:41","27/06/2015 15:43"],
                        'gender': ["male","female","female","male","male","female","female",np.nan,"male","male","female","male","female","female","male","female","male","female",np.nan,"male"],
                        'age': ["young","old","old","old","old","old",np.nan,"old","old","young","young","old","young","young","old",np.nan,"old","young",np.nan,np.nan]})

# Convert date to datetime
tempDF['date'] = pd.to_datetime(tempDF['date'])

# Create groupby object based on two categorical variables
tempGroupby = tempDF.sort_values(['gender','age','id']).groupby(['gender','age'])

# Count number in each group and merge with original dataframe to create 'count' column
tempCountsDF = tempGroupby['id'].count().reset_index(drop=False)
tempCountsDF = tempCountsDF.rename(columns={'id': 'count'})
tempDF = tempDF.merge(tempCountsDF, on=['gender','age'])

# Calculate difference between consecutive rows in each group. (First row in each
# group should have date difference = NaT)
# ****** THIS TIME THE FOLLOWING GROUPBY DEFINITION IS COMMENTED OUT ***** 
# tempGroupby = tempDF.sort_values(['gender','age','id']).groupby(['gender','age'])
tempDF['diff'] = tempGroupby['date'].diff()
print(tempDF)

而且,这次输出非常不同(而不是我想要的)

age                date  gender  id  count                diff
0   young 2015-02-04 02:34:00    male   1      2                 NaT
1   young 2015-10-05 08:52:00    male  10      2                 NaT
2     old 2015-06-04 12:34:00  female   2      3    92 days 10:29:00
3     old 2015-09-04 23:03:00  female   3      3                 NaT
4     old 2015-04-21 12:59:00  female   6      3 -233 days +06:12:00
5     old 2015-12-04 01:00:00    male   4      6 -137 days +13:56:00
6     old 2015-04-15 07:12:00    male   5      6                 NaT
7     old 2015-06-05 11:12:00    male   9      6                 NaT
8     old 2015-05-19 19:22:00    male  12      6    51 days 04:00:00
9     old 2015-04-06 12:57:00    male  15      6   243 days 06:18:00
10    old 2015-06-15 03:23:00    male  17      6                 NaT
11  young 2015-12-05 14:19:00  female  11      4  -17 days +08:10:00
12  young 2015-05-27 22:31:00  female  13      4 -192 days +08:12:00
13  young 2015-01-06 11:09:00  female  14      4 -142 days +12:38:00
14  young 2015-06-19 05:37:00  female  18      4  -44 days +17:35:00

(在我的现实剧本中,结果似乎有点不稳定,有时候它会起作用,有时却不行 . 但在上面的剧本中,不同的输出似乎始终如一 . )

为什么有必要在使用.diff()函数之前立即重新创建基于相同数据帧的groupby对象(尽管添加了一个额外的列)?这对我来说似乎非常危险 .

1 回答

  • 2

    不一样,索引也发生了变化 . 例如:

    tempDF.loc[1].id  # before
    
    10
    
    tempDF.loc[1].id  # after
    
    2
    

    因此,如果您使用旧的 tempDF 计算 tempGroupby ,然后在执行此操作时更改 tempDF 中的索引:

    tempDF['diff'] = tempGroupby['date'].diff()
    

    索引与您期望的不匹配 . 您将为每一行分配与旧 tempDF 中具有该索引的行相对应的差异 .

相关问题