我有一个数据框,其中第一列是时间,第二列是字母:
Time Letter
2016-10-05 20:46:12 'A'
2016-10-05 20:47:12 'A'
2016-10-05 20:50:12 'B'
2016-10-06 00:46:12 'A'
2016-10-06 01:46:12 'B'
2016-10-06 01:47:12 'C'
2016-10-06 02:46:12 'D'
我需要按小时对数据进行分组,并计算每小时唯一字母的数量:
Time Unique_values
2016-10-05 20 2
2016-10-06 00 1
2016-10-06 01 2
2016-10-06 00 1
df.groupby([df.index.date,df.index.hour]).Letter.nunique().plot(kind = 'bar', rot =0)
提供带有标签的图表(2016-10-05,7),(2016-10-05,8)......
有没有办法删除括号而不是7,8等使用07:00:00,08:00:00?
答案 0 :(得分:0)
您可以使用pd.Grouper:
df.groupby(pd.Grouper(key='Time', freq='H'))['Letter'].nunique()
或者将时间列设置为索引并重新取样:
df.set_index('Time').resample('H')['Letter'].nunique()
两者都将用零填充缺失的间隔。既然你正在策划,我猜你想要那样。如果没有,您可以将结果系列分配给变量并过滤:
ser = df.groupby(pd.Grouper(key='Time', freq='H'))['Letter'].nunique()
ser = ser[ser>0]
由于bug,nunique可能无法在当前版本中正常运行。 @jcrist提供的解决方法是使用带有agg的pd.Series.nunique。因此,您可以将上述代码更新为:
df.groupby(pd.Grouper(key='Time', freq='H'))['Letter'].agg(pd.Series.nunique)
或者,
df.set_index('Time').resample('H')['Letter'].agg(pd.Series.nunique)
答案 1 :(得分:0)
您可以通过values
然后Time
将numpy array
列转换为groupby
来删除分钟和秒数:
print (df.Time.values.astype('<M8[h]'))
['2016-10-05T20' '2016-10-05T20' '2016-10-05T20' '2016-10-06T00'
'2016-10-06T01' '2016-10-06T01' '2016-10-06T02']
print (df.groupby([df.Time.values.astype('<M8[h]')])['Letter'].nunique())
2016-10-05 20:00:00 2
2016-10-06 00:00:00 1
2016-10-06 01:00:00 2
2016-10-06 02:00:00 1
Name: Letter, dtype: int64
<强>计时强>:
In [72]: %timeit (df.groupby([df.Time.values.astype('<M8[h]')])['Letter'].nunique())
100 loops, best of 3: 7.94 ms per loop
In [73]: %timeit (ayh1(df1))
1 loop, best of 3: 301 ms per loop
In [74]: %timeit (ayh2(df2))
1 loop, best of 3: 298 ms per loop
<强>代码强>:
start = pd.to_datetime('2015-02-24 20:00:15')
rng = pd.date_range(start, periods=10000, freq='40T')
df = pd.DataFrame({'Time': rng,
'Letter': np.random.choice(list(ascii_letters.upper()), (10000,))})
print (df)
df1 = df.copy()
df2 = df.copy()
def ayh1(df):
ser = df.groupby(pd.Grouper(key='Time', freq='H'))['Letter'].agg(pd.Series.nunique)
return ser[ser>0]
def ayh2(df):
ser = df.set_index('Time').resample('H')['Letter'].agg(pd.Series.nunique)
return ser[ser>0]
print (df.groupby([df.Time.values.astype('<M8[h]')])['Letter'].nunique())
print (ayh1(df1))
print (ayh2(df2))