Aggregate and plot time series in pandas

If date is the index, you can use resample with the SemiMonthStart ('SMS') frequency:

df.index = pd.to_datetime(df.index)
df.resample('SMS').count()

Output:

            id
date          
2018-01-01   4
2018-01-15   3

You can also use date offsets (here SemiMonthBegin) to round your dates and use this result to groupby+count:

group = (pd.to_datetime(df['date'])
           .apply(pd.offsets.SemiMonthBegin().rollback)
           )

out = df.groupby(group)['id'].count()

Output:

date
2018-01-01    4
2018-01-15    3
Name: id, dtype: int64