【问题标题】:Resample pandas dataframe and apply mode重新采样熊猫数据框并应用模式
【发布时间】:2018-07-05 00:14:32
【问题描述】:

我想计算 pandas 数据框中每组重采样行的模式。我是这样尝试的:

import datetime
import pandas as pd
import numpy as np
from statistics import mode


date_times = pd.date_range(datetime.datetime(2012, 4, 5),
                           datetime.datetime(2013, 4, 5),
                           freq='D')
a = np.random.sample(date_times.size) * 10.0

frame = pd.DataFrame(data={'a': a},
                     index=date_times)

frame['b'] = np.random.randint(1, 3, frame.shape[0])
frame.resample("M").apply({'a':'sum', 'b':'mode'})

但它不起作用。

我也试试:

frame.resample("M").apply({'a':'sum', 'b':lambda x: mode(frame['b'])})

但是我得到了错误的结果。有什么想法吗?

谢谢。

【问题讨论】:

  • 如果有多个最常见的值,statistics.mode 会引发 StatisticsError。当这种情况发生在重采样组中时,您希望frame 中的值是多少?
  • 我已经接受了 scipy.stats.mode 解决方案的答案,该解决方案导致两者中最小的一个。但是假设我想要最大的,我将如何控制它?
  • 我不知道执行此操作的内置函数。下面,我修改了我的答案,通过制作value_counts 的表格,然后按计数和b 值降序排序来展示一种方法。然后,当您按日期分组时,每个组中最大的 b 值将位于顶部。

标签: python pandas dataframe mode


【解决方案1】:

frame.resample("M").apply({'a':'sum', 'b':lambda x: mode(frame['b'])}) 中,每个重采样组都会调用一次 lambda 函数。 x 分配给一个 Series,其值来自重采样组的 b 列。

lambda x: mode(frame['b']) 忽略x 并简单地返回frame['b'] 的模式——整个列。

相反,你会想要类似的东西

frame.resample("M").apply({'a':'sum', 'b':lambda x: mode(x)})

但是,这会导致StatisticsError

StatisticsError: no unique mode; found 2 equally common values

因为有一个重采样组具有多个最常见的值。

如果您改用scipy.stats.mode,则返回最小的最常见值:

import datetime
import pandas as pd
import numpy as np
import scipy.stats as stats

date_times = pd.date_range(datetime.datetime(2012, 4, 5),
                           datetime.datetime(2013, 4, 5),
                           freq='D')
a = np.random.sample(date_times.size) * 10.0
frame = pd.DataFrame(data={'a': a}, index=date_times)
frame['b'] = np.random.randint(1, 3, frame.shape[0])

result = frame.resample("M").apply({'a':'sum', 'b':lambda x: stats.mode(x)[0]})
print(result)

产量

            b           a
2012-04-30  2  132.708704
2012-05-31  2  149.103439
2012-06-30  2  128.492203
2012-07-31  2  142.167672
2012-08-31  2  126.516689
2012-09-30  1  133.209314
2012-10-31  2  136.684212
2012-11-30  2  165.075150
2012-12-31  2  167.064212
2013-01-31  1  150.293293
2013-02-28  1  125.533830
2013-03-31  2  174.236113
2013-04-30  2   11.254136

如果您想要最大最常用的值,那么不幸的是,我不知道有任何内置函数可以为您执行此操作。在这种情况下,您可能需要计算一个 value_counts 表:

In [89]: counts
Out[89]: 
            b  counts
2012-04-30  3      11
2012-04-30  2      10
2012-04-30  1       5
2012-05-31  2      14
2012-05-31  1       9
2012-05-31  3       8

然后按countsb 的值降序对其进行排序,按日期分组并取每组中的第一个值:

import datetime as DT
import numpy as np
import scipy.stats as stats
import pandas as pd
np.random.seed(2018)

date_times = pd.date_range(DT.datetime(2012, 4, 5), DT.datetime(2013, 4, 5), freq='D')
N = date_times.size
a = np.random.sample(N) * 10.0
frame = pd.DataFrame(data={'a': a, 'b': np.random.randint(1, 4, N)}, index=date_times)

resampled = frame.resample("M")
sums = resampled['a'].sum()
counts = resampled['b'].value_counts()
counts.name = 'counts'
counts = counts.reset_index(level=1)
counts = counts.sort_values(by=['counts','b'], 
                             ascending=[False,False])
result = counts.groupby(level=0).first()

产量

            b  counts
2012-04-30  3      11
2012-05-31  2      14
2012-06-30  3      12
2012-07-31  2      12
2012-08-31  2      11
2012-09-30  3      12
2012-10-31  2      13
2012-11-30  3      13
2012-12-31  2      14
2013-01-31  3      14
2013-02-28  1      10
2013-03-31  3      13
2013-04-30  3       2

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-12
    • 2020-01-10
    • 2018-03-26
    • 2020-11-18
    • 2016-03-19
    • 1970-01-01
    • 2018-11-16
    相关资源
    最近更新 更多