我有一个数据框数据
groupId service local
0 1 s1 l1
1 1 s1 l1
2 1 s2 l2
3 1 s3 l3
4 2 s2 l2
5 2 s3 l3
6 3 s1 l1
7 3 s2 l2
我有一个数据框问题
q1 q2 howManyGroups
0 s1 l1 0
1 s1 s2 0
2 s2 l2 0
3 s3 l3 0
4 s3 l1 0
我想根据数据中出现的组数来计算问题行的出现次数:
q1 q2 howManyGroups
0 s1 l1 2
1 s1 s2 2
2 s2 l2 3
3 s3 l3 2
4 s3 l1 1
我正在使用此代码,但是它确实很慢:
for i,g in data.groupby('groupId'):
for j,r in question.iterrows():
if set(r[['q1','q2']].values).issubset(set( g.drop('groupId', axis=1).values.ravel())):
question.loc[j,'howManyGroups'] += 1
编辑:我的问题数据框有时可以包含比q1 and q2
更多/更少的列。有时只有q1
,有时只有q1, q2, q3
...
答案 0 :(得分:1)
您可以做的是首先重塑数据,以使groupID和任何列服务或本地中的唯一值都获得一行。
data_ = (data.set_index('groupId').stack()
.reset_index(name='h')
[['groupId', 'h']].drop_duplicates()
)
print (data_.head())
groupId h
0 1 s1
1 1 l1
4 1 s2
5 1 l2
6 1 s3
然后使用问题和merge
两次,第一次仅在q1上(和data_中的h)获得与q1关联的groupId,第二次在q2和groupId上确保q1和q2在同一组中。最后,groupby
在合并之前与reset_index一起保存的原始索引,并在groupId上使用nunique
:
question['howManyGroups'] = (question[['q1','q2']].reset_index()
.merge(data_, left_on=['q1'], right_on=['h'])
.merge(data_, left_on=['q2','groupId'],
right_on=['h','groupId'])
.groupby('index')['groupId'].nunique()
)
print (question)
q1 q2 howManyGroups
0 s1 l1 2
1 s1 s2 2
2 s2 l2 3
3 s3 l3 2
4 s3 l1 1
如果您不知道qi的数量,可以尝试以下方法:
df_tmp = (question.reset_index()
.merge(data_, left_on=['q1'], right_on=['h'])
)
l_q = question.filter(regex='q\d*').columns.tolist()
l_q.remove('q1')
for q in l_q:
df_tmp = df_tmp.merge(data_, left_on=[q,'groupId'], right_on=['h', 'groupId'])
question['howManyGroups'] = df_tmp.groupby('index')['groupId'].nunique()