我是一个Pandas DF,其他列中有一个日期列和一个ID列。我需要按日期对此数据进行分组/排序,并且每个日期计算自第一行(时间轴的开始)以来看到的唯一ID的数量。有没有办法用pandas / numpy做这个而不用写出循环?
答案 0 :(得分:2)
了解pandas.unique:
import pandas as pd
for date in pd.unique(df['Date']):
unique_ids = pd.unique(df[df['Date']==date]['id'])
print len(unique_ids)
编辑第二次尝试
newdf = df[['Date', 'id']].drop_duplicates()
newdf.groupby('Date').count()
答案 1 :(得分:2)
至少现在很清楚OP想要什么......
print(df.groupby('date').id.nunique().cumsum())
测试数据集:
date;id
2012-03-31;111
2012-03-31;2
2012-03-31;1
2012-03-31;4
2012-04-01;15
2012-04-01;6
2012-04-01;7
2012-04-01;118
2012-04-01;9
2012-05-01;10
2012-05-01;11
两种不同方法的比较:
import pandas as pd
df = pd.read_csv('data.csv', sep=';').sort('date')
print(df[['date','id']].drop_duplicates(['id']).groupby('date').count().cumsum())
print(df.groupby('date').id.nunique().cumsum())
输出:
id
date
2012-03-31 4
2012-04-01 9
2012-05-01 11
date
2012-03-31 4
2012-04-01 9
2012-05-01 11
Name: id, dtype: int64
PS所以它确实返回了正确的结果。至少对于那个数据集。这就是为什么提供测试数据集和预期输出很重要的原因!
PPS另一个有趣的观察结果:from timeit import Timer
import pandas as pd
df = pd.read_csv('data.csv', sep=';', parse_dates=['date']).sort_values(['date'])
def drop_dups():
df[['date','id']].drop_duplicates(['id']).groupby('date').count().cumsum()
def nunique():
df.groupby('date').id.nunique().cumsum()
print('drop_dups():\t{:.6f}'.format(Timer(drop_dups).timeit(1000)))
print('nunique():\t{:.6f}'.format(Timer(nunique).timeit(1000)))
输出:
drop_dups(): 6.722572
nunique(): 1.512233
答案 2 :(得分:1)
由于其余答案都无法解决我的问题,因此我对以下代码段进行了编码。
因此,此代码段将包含从每次迭代开始到最近一周的唯一ID数量。上述答案给了我这些唯一ID的累积和,从而导致不匹配。
ex:用于以下输入:
周号
2020-12-04 101
2020-12-04 102
2020-12-11 101
2020-12-11 103
此处提到的其他代码的输出:
2020-12-04:2
2020-12-11:4
我想要的输出是:
2020-12-04:2
2020-12-11:3
此代码段是:
for date in pd.unique(df['week']):
print(date,"\t",df[df['week']<=date].id.nunique())
我不确定OP是否希望获得相同的输出,但这只是为了防止有人以我提到的方式需要输出