在熊猫中,使用通过列表列表过滤的数据创建新的数据框

时间:2019-02-14 01:11:45

标签: python pandas

因此,我已经四处张望,但找不到该问题的答案。我很抱歉是否确实在那里。

我有一个看起来像这样的DF:

a = pd.DataFrame({'Name': ['apple', 'banana', 'orange', 'apple', 'banana','orange'], 
                  'Units': [2,4,6,5,4,3]})

我还有一个这样的列表列表:

b = [['apple', 'banana'],['orange']]

目标是将苹果和香蕉分成1列,将桔子分为另一列,并将它们各自的单位相加。列中的变量将显示为子列表中的第一项。 (任何子列表都不会重复)。

这是我希望输出df看起来像的样子:

output = pd.DataFrame({'Name': ['apple', 'orange'],
               'Units': [15, 9]})

我现在在这里:

for fruit in a['Name']:
for sublist in b:
    if fruit in sublist:
        pd.concat([XYZ,
                   pd.DataFrame({'Name': sublist[0], 'Units': a[a.Name == fruit]['Units'].sum(), index=[0})], 
                  axis=1)

XYZ是一个空数据框,其列=名称和我要用结果填充的单位。当水果在子列表中以及其单位的总和时,我真的不太了解如何创建数据框。

有什么想法吗? :D

编辑:子列表的范围为1到300个项目。这里的代码只是一个更大的数据处理问题的MWE。抱歉,没有提到这一点。

4 个答案:

答案 0 :(得分:1)

实际上,您可以在一行中完成此操作:

sum_a = a.replace({"banana": "apple"}).groupby("Name", as_index=False).sum()

答案 1 :(得分:1)

IIUC,最好重新创建对象,而不是更改原始df,因为replace仍然会丢失有关apple的信息,因为您将苹果替换为香蕉。因此,输出结果会仅包含有关applebanana

的信息
d={','.join(x):a.loc[a.Name.isin(x),'Units'].sum() for x in b }
pd.Series(d)
apple,banana    15 # here you do not losing the information of each items in the list 
orange           9
dtype: int64

答案 2 :(得分:0)

使用pd.Series.isin和布尔索引:

pd.DataFrame([(l[0], a.Units[a.Name.isin(l)].sum()) for l in b], columns=['Name', 'Units'])
     Name  Units
0   apple     15
1  orange      9

答案 3 :(得分:0)

另一种解决方案是制作一个同时返回名称和总和值的函数。

from operator import itemgetter

first = itemgetter(0)

def make_rows(cols, df):
    for col in cols:
        name = first(col)
        val = df.loc[df.Name.str.contains('|'.join(col), regex=True), 'Units'].sum()
        yield name, val

df1 = pd.DataFrame(make_rows(b, a), columns=a.columns)

print(df1)

     Name  Units
0   apple     15
1  orange      9

另外也是如此:

from functools import partial

def make_rows(df, col):
    name = first(col)
    val = df.loc[df.Name.str.contains('|'.join(col), regex=True), 'Units'].sum()
    return name, val

p = partial(make_rows, a)

pd.DataFrame(list(map(p, b)), columns=a.columns)

     Name  Units
0   apple     15
1  orange      9