Csv pandas groupby的中位数“修改了”

时间:2019-12-31 06:35:12

标签: python pandas csv group-by median

我想使用“计数”列按日期和时间组合对数据集进行“修改”的df.groupby.median()。

以下是我正在使用的数据集的示例:

              date    time    count
0         20160730    02:30     415
1         20160730    02:30      18
2         20160730    02:30      24
3         20160730    02:30      31
4         20160730    13:30      64
...            ...      ...     ...
169549    20170101    23:45      29
169550    20170101    23:45      34
169551    20170101    23:45      43
169552    20170101    23:45      42
169553    20170101    23:45      60

挑战是,我想计算一个也计入未录入的中位数。

在数据集中,每个“日期”和“时间”组合最多有6行,因为数据是从6个单独的位置收集的。但是,如果特定日期/时间/地点组合的“计数”为0,则数据不会直接输入到数据集中。

(我已在上面的示例数据中删除了“位置”列,但是如果需要的话,它是可用的。)

这意味着,如果我使用通常的df.groupby.median()函数,我将高估数据的真实中位数,因为它将忽略未输入的零。

本质上,我想计算一个修改后的中位数,如下所示:

For each date and time combination:
   count_rows = count number of rows that satisfy the date and time combination
   if count_rows == 6:
      mod_median = median of the 6 rows
   elif count_rows == 5 or count_rows == 4:
      mod_median = average of the 3rd and 4th highest row values
   elif count_rows == 3:
      mod_median = half of the lowest row value
      # true median == median of [0, 0, 0, value1, value2, value3]
   else
      mod_median = 0
      # true median == zero for count_rows <= 2

我该如何实现?有没有比我上面写的更有效的逻辑来解决这个问题?

预先感谢

1 个答案:

答案 0 :(得分:1)

您可以在DataFrame.sort_values之前的GroupBy.apply中使用自定义功能:

def cust_med(x):
    len1 = len(x.index)
    if len1 == 6:
        return x['count'].median()
    if (len1 == 5) or (len1 == 4):
        #3rd and 4th higher values
        return x.iloc[[2,3], x.columns.get_loc('count')].mean()
    if len1 == 3:
        #added 3 values with np.median
        return np.median(np.concatenate([[0,0,0], x['count']]))
    else:
        return 0

df = (df.sort_values(['date','time', 'count'], ascending=[True, True, False])
       .groupby(['date','time']).apply(cust_med)
       .reset_index(name='custom median'))