根据来自另一个的组值填充一个数据框

时间:2020-06-08 13:45:17

标签: python numpy dataframe

我有一个数据框数据

   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 ...

1 个答案:

答案 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()