猿问

使用另一个列表中的键聚合一个列表

我有一个包含刺痛和浮点数列表的数据框,可以说


                        Names                    Prob

           [Anne, Mike, Anne]      [10.0, 10.0, 80.0]

   [Sophie, Andy, Vera, Kate]  [30.0, 4.5, 5.5, 60.0]

         [Josh, Anne, Sophie]            [51, 24, 25]

我想要做的是循环Names,如果名称包含在预定义的组中,则重新标记它,然后从Prob.


例如,如果team1 = ['Anne', 'Mike', 'Sophie']我想结束:


                          Names                    Prob

                     [Team_One]                 [100.0]

   [Andy, Kate, Team_One, Vera]  [4.5, 60.0, 30.0, 5.5]

               [Josh, Team_One]                [51, 49]

我写的是这个,但我认为这有点荒谬,我在循环内创建一个临时数据框,然后进行分组;对我来说听起来有点矫枉过正,而且太重了。


请问有没有更有效的方法?(如果重要的话,我正在使用 Python 3)


import pandas as pd



def pool(df):

    team1 = ['Anne', 'Mike', 'Sophie']


    names = df['Names']

    prob = df['Prob']

    out_names = []

    out_prob = []

    for key, name in enumerate(names):

        # relabel if in team1 otherwise keep it the same

        name = ['Team_One' if x in team1 else x for x in name]


        # make a temp dataframe and group by name

        temp = pd.DataFrame({'name': name, 'prob': prob[key]} )

        temp = temp.groupby('name').sum()


        # make the output

        out_names.append(temp.index.tolist())

        out_prob.append(temp['prob'].tolist())


    df['Names'] = out_names

    df['Prob'] = out_prob

    return df



df = pd.DataFrame({

    'Names':[['Anne', 'Mike', 'Anne'],

             ['Sophie', 'Andy', 'Vera', 'Kate'],

             ['Josh', 'Anne', 'Sophie']

    ],

    'Prob': [[10., 10., 80.],

             [30., 4.5, 5.5, 60.],

             [51, 24, 25]

             ]

})



out = pool(df)

print(out)

谢谢!


暮色呼如
浏览 154回答 2
2回答

陪伴而非守候

用于defaultdict对列表中的所有值求和,然后将其转换为元组列表并传递给 DataFrame 构造函数:from collections import defaultdictout = []for a, b in zipped:    d = defaultdict(int)    for x, y in zip(a, b):        if x in team1:            d['Team_One'] +=y        else:            d[x] = y    out.append((list(d.keys()), list(d.values())))df = pd.DataFrame(out, columns=['Names','Prob'])print (df)                          Names                    Prob0                    [Team_One]                 [100.0]1  [Team_One, Andy, Vera, Kate]  [30.0, 4.5, 5.5, 60.0]2              [Josh, Team_One]                [51, 49]如果没有0值,解决方案工作Prob:out = []for a, b in zipped:    n, p = [],[]    tot = 0    for x, y in zip(a, b):        if x in team1:            tot +=y        else:            n.append(x)            p.append(y)    if tot != 0:            p.append(tot)        n.append('Team_One')    out.append((n, p))df = pd.DataFrame(out, columns=['Names','Prob'])print (df)                          Names                    Prob0                    [Team_One]                 [100.0]1  [Andy, Vera, Kate, Team_One]  [4.5, 5.5, 60.0, 30.0]2              [Josh, Team_One]                [51, 49]在 Pandas 中处理列表在列中很慢,所以最好先展平列表:from itertools import chainlens = [len(x) for x in df['Names']]df = pd.DataFrame({    'row' : np.arange(len(df)).repeat(lens),    'Names' : list(chain.from_iterable(df['Names'].tolist())),     'Prob' : list(chain.from_iterable(df['Prob'].tolist()))})然后用isin最后一个聚合替换值sum:team1 = ['Anne', 'Mike', 'Sophie']df.loc[df['Names'].isin(team1), 'Names'] = 'Team_One'df = df.groupby(['row','Names'], as_index=False, sort=False)['Prob'].sum()print (df)   row     Names   Prob0    0  Team_One  100.01    1  Team_One   30.02    1      Andy    4.53    1      Vera    5.54    1      Kate   60.05    2      Josh   51.06    2  Team_One   49.0

繁花不似锦

似乎没有办法绕过创建新列表来替换旧列表,因为从原始列表中删除项目成本太高。我认为这可能是通过名称和概率的可行解决方案,如果名称不在 team1 中,请将名称和概率附加到新列表中。如果名称在 team1 中,则不要添加该名称,而是保留针对 team1 名称遇到的问题的总和。如果在遍历行的每个名称后该总和不为零,则至少找到了一个 team1 成员(假设所有概率都是正数,如果为真,则 idk)。然后最后,我们将“Team_One”作为名称和 probs 的总和附加到 probs 列表(如果 sum 非零),并用这些新创建的列表替换数据框的列表。def pool(df):    # Set of team1 names for faster look up than a list    team1 = {'Anne', 'Mike', 'Sophie'}    for i, names in enumerate(df['Names']):        # iterating through every row and initializing new lists to replace the name/prob lists        new_names = []        new_probs = []        team1_prob = 0        for name, prob in zip(names, df['Probs'][i]):            # iterating through every name/prob pair.            if name not in team1:                # add the pair to the new lists if not in team1                new_names.append(name)                new_probs.append(prob)            else:                # keep a sum of probs for all team1 members found, but don't append their name                team1_prob += prob        if team1_prob != 0:            # assuming all probs are positive, thus if any team1 member was found, team1_prob must be nonzero            new_names.append('Team_One')            new_probs.append(team1_prob)        # replace lists in the original df        df['Names'][i] = new_names        df['Prob'][i] = new_probs    return df
随时随地看视频慕课网APP

相关分类

Python
我要回答