在熊猫中绘制唯一值

时间:2016-10-06 04:12:28

标签: python pandas

我有一个数据框,其中第一列是时间,第二列是字母:

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?

2 个答案:

答案 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然后Timenumpy 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))