【问题标题】:Efficient method for generating a list of values from a column in a data frame based on common secondary columns基于公共辅助列从数据框中的列生成值列表的有效方法
【发布时间】:2020-03-31 11:32:58
【问题描述】:

我在 Python 中有一个数据框 (df),它有 4 列(ID、Status、Person、Output)。每个 ID 重复 6 次,每个 ID 的输出相同。对于每个 ID,状态将为开/关(每个 3 个)。

我需要为每个唯一 ID/状态组合生成一个包含人员列表的新列。我还需要第二个新列,其中包含每个唯一人员列表的组 ID。

这是我当前的代码,由于 apply(list) 函数,它在处理大型数据帧时可以运行但速度很慢。有没有更有效的方法来做到这一点?

people = df.groupby(['ID','Status'])['Person'].apply(list).reset_index(name='Names_ID')
people['Group_ID'] = people['Names_ID'].rank(method='dense')
df = df.drop_duplicates(subset=['ID','Status'])
df = df.merge(people, on = ('ID', 'Status'))

这是一个示例输入数据框:

df=
ID  Status  Person  Output
0   On  John    1
0   On  Mark    1
0   On  Michael 1
0   Off Peter   1
0   Off Tim     1
0   Off Jake    1
1   On  Peter   0.5
1   On  Dennis  0.5
1   On  Jasper  0.5
1   Off John    0.5
1   Off Mark    0.5
1   Off Michael 0.5
2   On  John    2
2   On  Mark    2
2   On  Larry   2
2   Off Peter   2
2   Off Dennis  2
2   Off Jasper  2

想要的输出是:

df =
ID  Status  People                Group_ID  Output
0   On  [John, Mark, Michael ]      0       1
0   Off [Peter, Tim, Jake ]         1       1
1   On  [Peter, Dennis, Jasper ]    2       0.5
1   Off [John, Mark, Michael ]      0       0.5
2   On  [John, Mark, Larry ]        3       2
2   Off [Peter, Dennis, Jasper ]    2       2

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    试试这个:

    df_out = df.groupby(['ID', 'Status'])['Person'].apply(list).reset_index()
    df_out['Group_ID'] = pd.factorize(df_out['Person'].apply(tuple))[0]
    df_out
    

    输出:

       ID Status                   Person  Group_ID
    0   0    Off       [Peter, Tim, Jake]         0
    1   0     On    [John, Mark, Michael]         1
    2   1    Off    [John, Mark, Michael]         1
    3   1     On  [Peter, Dennis, Jasper]         2
    4   2    Off  [Peter, Dennis, Jasper]         2
    5   2     On      [John, Mark, Larry]         3
    

    或

    df_out = df.groupby(['ID', 'Status'])['Person'].apply(', '.join).reset_index()
    df_out['Group_ID'] = pd.factorize(df_out['Person'])[0]
    df_out
    

    【讨论】:

    • 比我的简单多了。我得研究这个。不过,您省略了“输出”。我没有意识到您可以在 groupby 的末尾使用 .apply,尤其是列表。
    【解决方案2】:
    import pandas as pd
    df = pd.read_clipboard()
    df
    

    一种方法是使用shift 两次并将三列连接成一个列表。然后使用groupby 找出 Group_ID 并使用merge 将其返回到数据帧中。

    df['Person1'] = df['Person'].shift(-1)
    df['Person2'] = df['Person'].shift(-2)
    df['People'] = '[' + df['Person'] + ',' + df['Person1'] + ',' + df['Person2'] + ']'
    mult_3 = []
    for i in df.index:
        if i==0 or i%3 == 0:
            mult_3.append(i)
    df = df.loc[df.index.isin(mult_3)].drop(['Person', 'Person1', 'Person2'], axis=1)
    df_people = df.groupby('People').Status.count().reset_index().drop(['Status'], axis=1).reset_index()
    df = df.merge(df_people, how='left', on='People').rename(columns={'index':'Group_ID'})
    df = df[['ID', 'Status', 'People', 'Group_ID', 'Output']]
    df
    

    【讨论】:

      【解决方案3】:

      Python 3.7.6 和 Pandas 1.0.3:这里的瓶颈可能是 apply 调用。

      people = df.groupby(['ID','Status', "Output"])['Person'].apply(list).reset_index(name = 'People')
      people['Group_ID'] = people["People"].apply(str).astype('category').cat.codes
      

      输出:

        ID Status Output                   People  Group_ID
      0  0    Off      1       [Peter, Tim, Jake]         3
      1  0     On      1    [John, Mark, Michael]         1
      2  1    Off    0.5    [John, Mark, Michael]         1
      3  1     On    0.5  [Peter, Dennis, Jasper]         2
      4  2    Off      2  [Peter, Dennis, Jasper]         2
      5  2     On      2      [John, Mark, Larry]         0
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-07-21
        • 1970-01-01
        • 2021-03-24
        • 1970-01-01
        • 2019-04-17
        • 1970-01-01
        • 1970-01-01
        • 2019-03-29
        相关资源
        最近更新 更多