Pandas:如果多个值匹配str / contains / join,则为列中的值

时间:2017-11-17 18:38:13

标签: python pandas dataframe sum

我无法从另一个数据框中的一个数据框中搜索一个数字列表。我正在处理一个案例,其中不同的数字指的是同一个项目。 我无法从另一个数据框中的一个数据框中搜索一个数字列表。我正在处理一个案例,其中不同的数字指的是同一个项目。

在我的示例代码中,“term2”包含代码为“AAAA”和“CCCC”的条目。

    df1 = pd.DataFrame(
        {
        'term' : ['term1','term2','term3','term4','term1','term3','term2'],
        'code': ['ZZZZ', 'AAAA','XXXX','QQQQ','ZZZZ','XXXX','CCCC'],
        'count':['1','3','1','1','1','1','3']
        }
        )
df1 = df1[['term'] + df1.columns[:-1].tolist()]
df2 = pd.DataFrame(
        {
        'name': ['Dan','Sara','Conroy','Steve'],
        'rate': ['3','3.5','5.2','3'],
        'location': ['FL','OH','NM','NM'],
        'code': ['XXXX','BBBB','PPPP','TTTT'],
        'allcodes': ['XXXX,YYYY,ZZZZ','AAAA,BBBB,CCCC','PPPP,QQQQ,RRRR','SSSS,TTTT,UUUU']
         }
         )

df2 = df2[['name','rate','location','code','allcodes']]
pmissnlist = df1['code'].values.tolist()
df3 = df2[df2['allcodes'].str.contains('|'.join(pmissnlist))].reset_index()

df4 = pd.DataFrame(df3['allcodes'].str.split(',').tolist(),
                            index=df3.code).stack(level=0).reset_index(level=0)
matches = df4[df4[0].isin(df1.code)]
df5 = df3[df3.code.isin(matches.code)]
df5 = df5.drop_duplicates()#drops duplicate rows

df5_temp = df5.set_index(['name','rate','location','code']).allcodes.str.split(',',expand = True)\
                                  .stack().reset_index(4,drop = True).reset_index(name = 'allcodes')
df5 = pd.merge(df1, df5_temp, left_on = 'code', right_on = 'allcodes')
df5 = df5.drop('allcodes', 1).groupby(['code_y','term','count','name','rate','location']).code_x.\
                                    apply(','.join).reset_index().sort_values(by='count', ascending=False)
print(df5)

输出结果为:

      code_y   term   count  name   rate  location  code_x
0     BBBB     term2  3      Sara   3.5   OH        AAAA,CCCC
1     PPPP     term4  1      Conroy 5.2   NM        QQQQ
2     XXXX     term1  1      Dan    3     FL        ZZZZ,ZZZZ
3     XXXX     term3  1      Dan    3     FL        XXXX,XXXX

有两个与Sara关联的term2实例,所以我希望她的数量为6,而不是3.对于每个Dan的行,计数也应为2。如果我正确理解了数据帧,那么这是预期的:数据帧包含满足第一个term2条件的数据。比较第二个实例时,相关数据已存在于数据框中。

如何在df2的“allcode”字段中对多个代码匹配的计数值求和?

编辑:添加所需的结果

      code_y   term   count  name   rate  location  code_x
0     BBBB     term2  6      Sara   3.5   OH        AAAA,CCCC
1     PPPP     term4  1      Conroy 5.2   NM        QQQQ
2     XXXX     term1  2      Dan    3     FL        ZZZZ,ZZZZ
3     XXXX     term3  2      Dan    3     FL        XXXX,XXXX

EDIT2: 问题出在groupby上。

这是df5在输出groupby之前的输出:

    term code_x  count    name rate location code_y allcodes
0  term1   ZZZZ      1     Dan    3       FL   XXXX     ZZZZ
1  term1   ZZZZ      1     Dan    3       FL   XXXX     ZZZZ
2  term2   AAAA      3    Sara  3.5       OH   BBBB     AAAA
3  term3   XXXX      1     Dan    3       FL   XXXX     XXXX
4  term3   XXXX      1     Dan    3       FL   XXXX     XXXX
5  term4   QQQQ      1  Conroy  5.2       NM   PPPP     QQQQ
6  term2   CCCC      2    Sara  3.5       OH   BBBB     CCCC
7  term6   TTTT      1   Steve    3       NM   TTTT     TTTT

所以,基本上我希望在groupby之前计算具有相同术语的列(Sara的term2,以及Dan的term3和term4)。

2 个答案:

答案 0 :(得分:2)

IIUC,使用str.splitlen

df['count']*=df['code_x'].str.split(',').apply(len)
df
Out[1105]: 
  code_y   term  count    name  rate location     code_x
0   BBBB  term2      6    Sara   3.5       OH  AAAA,CCCC
1   PPPP  term4      1  Conroy   5.2       NM       QQQQ
2   XXXX  term1      2     Dan   3.0       FL  ZZZZ,ZZZZ
3   XXXX  term3      2     Dan   3.0       FL  XXXX,XXXX

编辑:

    df.groupby(['code_y','term'],as_index=False).agg({'count':'sum','name':'first','rate':'first','location':'first','code_x':lambda x : ','.join(x),'allcodes':'first'})
Out[1130]: 
  code_y   term  count    name  rate location     code_x allcodes
0   BBBB  term2      5    Sara   3.5       OH  AAAA,CCCC     AAAA
1   PPPP  term4      1  Conroy   5.2       NM       QQQQ     QQQQ
2   TTTT  term6      1   Steve   3.0       NM       TTTT     TTTT
3   XXXX  term1      2     Dan   3.0       FL  ZZZZ,ZZZZ     ZZZZ
4   XXXX  term3      2     Dan   3.0       FL  XXXX,XXXX     XXXX

答案 1 :(得分:1)

我创建了一个小函数来获得预期的输出。

def f(x):
     return pd.Series(dict(count = x['count'].sum(), 
                        code_x = "%s" % ', '.join(x['code_x'])))

df5=df5.groupby(['code_y','term','name','rate','location'])[['code_x','count']].apply(f).reset_index()

输出

  code_y   term    name rate location      code_x  count
0   BBBB  term2    Sara  3.5       OH  AAAA, CCCC      6
1   PPPP  term4  Conroy  5.2       NM        QQQQ      1
2   XXXX  term1     Dan    3       FL  ZZZZ, ZZZZ      2
3   XXXX  term3     Dan    3       FL  XXXX, XXXX      2

https://stackoverflow.com/a/17841294/6626530启发