与列表列中的项目关联的总和金额

时间:2016-11-10 07:40:06

标签: python pandas dataframe

我的数据框如下:

print_r($_POST['my_val'])

我想总结与每个关键字相关联的金额。 注意:country letter keywords amount c y ['fruits', 'apples', "banana"] 700 c y ["music", "dance", "banana"] 150 c y ['loud', "dance", "apples"] 350 country并不总是相同的,就像上面设计的数据一样。此外,letters的列表大小不一。

我尝试了几种解决方案。我附上了我最快的一个。我还尝试了keywordsapply ...

的解决方案
defaultdicts

目标

keywords_list = []
for i in zip(*[df[c] for c in df.columns]):
    data = list(i[0:2])
    for k in i[2]:
        row = [k] + data + [i[-1]]
        keywords_list.append(row)

df_expanded = pd.DataFrame(keywords_list)
df_expanded.groupby(list(range(3)))[3].sum().reset_index()

编辑:目标示例中的更正错误

数据

  country letter keywords  amount
0       c      y   apples    1050
1       c      y   banana     850
2       c      y    dance     500
3       c      y   fruits     700
4       c      y     loud     350
5       c      y    music     150

2 个答案:

答案 0 :(得分:2)

您可以使用:

df1 = pd.DataFrame(df.keywords.values.tolist())
       .stack()
       .reset_index(level=1, drop=True)
       .rename('keywords')
print (df1)
0    fruits
0    apples
0    banana
1     music
1     dance
1    banana
2      loud
2     dance
2    apples
Name: keywords, dtype: object

print (df.drop('keywords', axis=1).join(df1).reset_index(drop=True))
  country letter  amount keywords
0       c      y     700   fruits
1       c      y     700   apples
2       c      y     700   banana
3       c      y     150    music
4       c      y     150    dance
5       c      y     150   banana
6       c      y     350     loud
7       c      y     350    dance
8       c      y     350   apples

另一种解决方案:

df = df.set_index(['country','letter','amount'])
df1 = pd.DataFrame(df.keywords.values.tolist(), index = df.index) \
        .stack() \
        .reset_index(name='keywords') \
        .drop('level_3',axis=1)
print (df1)
  country letter  amount keywords
0       c      y     700   fruits
1       c      y     700   apples
2       c      y     700   banana
3       c      y     150    music
4       c      y     150    dance
5       c      y     150   banana
6       c      y     350     loud
7       c      y     350    dance
8       c      y     350   apples

然后需要groupby聚合sum

print (df.groupby(['country','letter','keywords'], as_index=False)['amount'].sum())
  country letter keywords  amount
0       c      y   apples    1050
1       c      y   banana     850
2       c      y    dance     500
3       c      y   fruits     700
4       c      y     loud     350
5       c      y    music     150

<强>计时

In [47]: %timeit (df.set_index(['country','letter','amount']).keywords.apply(pd.Series).stack().reset_index().drop('level_3',1))
1 loop, best of 3: 4.55 s per loop

In [48]: %timeit (jez1(df3))
10 loops, best of 3: 24.8 ms per loop

In [49]: %timeit (jez2(df3))
10 loops, best of 3: 29.7 ms per loop

时间代码:

df = pd.concat([df]*10000).reset_index(drop=True)
df3 = df.copy()
df4 = df.copy()                

def jez1(df):
    df1 = pd.DataFrame(df.keywords.values.tolist()).stack().reset_index(level=1, drop=True).rename('keywords')
    return df.drop('keywords', axis=1).join(df1).reset_index(drop=True)

def jez2(df):
    df = df.set_index(['country','letter','amount'])
    df1 = pd.DataFrame(df.keywords.values.tolist(), index = df.index).stack().reset_index(name='keywords').drop('level_3',axis=1)
    return df1

感谢您MaxU改进pop - 然后不需要另一个drop。不幸的是timing失败了(KeyError: 'keywords'),所以我无法比较它。

答案 1 :(得分:1)

试试这个:

In [76]: (df.set_index(['country','letter','amount'])
    ...:    .keywords
    ...:    .apply(pd.Series)
    ...:    .stack()
    ...:    .reset_index(name='keywords')
    ...:    .drop('level_3',1)
    ...: )
    ...:
Out[76]:
  country letter  amount keywords
0       c      y     700   fruits
1       c      y     700   apples
2       c      y     700   banana
3       c      y     150    music
4       c      y     150    dance
5       c      y     150   banana
6       c      y     350     loud
7       c      y     350    dance
8       c      y     350   apples