重新采样 pandas 数据帧并应用模式
Resample pandas dataframe and apply mode
我想计算 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'])})
但是我得到了错误的结果。有什么想法吗?
谢谢。
在 frame.resample("M").apply({'a':'sum', 'b':lambda x: mode(frame['b'])})
中,lambda 函数为每个重采样组调用一次。 x
被分配给一个系列,其值来自重采样组的 b
列。
lambda x: mode(frame['b'])
忽略 x
并简单地 returns 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
table:
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
然后按 降序 按 counts
和 b
值排序,按日期分组并取每组中的第一个值:
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
我想计算 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'])})
但是我得到了错误的结果。有什么想法吗?
谢谢。
在 frame.resample("M").apply({'a':'sum', 'b':lambda x: mode(frame['b'])})
中,lambda 函数为每个重采样组调用一次。 x
被分配给一个系列,其值来自重采样组的 b
列。
lambda x: mode(frame['b'])
忽略 x
并简单地 returns 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
table:
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
然后按 降序 按 counts
和 b
值排序,按日期分组并取每组中的第一个值:
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