python - 根据条件将列值转换为列表的列

标签 python python-3.x pandas group-by pandas-groupby

数据集为:

   id  col2  col3
0   1     1   123
1   1     1   234
2   1     0   345
3   2     1   456
4   2     0  1243
5   2     0   346
6   3     0   888
7   3     0   999
8   3     0   777

我想通过 id 聚合数据,并将 col3 的值附加到列表中,只有当它在 col2 的对应值为1. 此外,对于在 col2 中只有 0 的人(不同 id),我希望 col2 的聚合值为 0 并且col3 的空列表。

这是当前代码:

df_test = pd.DataFrame({'id':[1, 1, 1, 2, 2, 2, 3, 3, 3], 'col2':[1, 1, 0, 1, 0, 0, 0, 0, 0], 'col3':[123, 234, 345, 456, 1243, 346, 888, 999, 777]})

df_test_agg = pd.pivot_table(df_test, index=['id'], values=['col2', 'col3'], aggfunc={'col2':np.max, 'col3':(lambda x:list(x))})

print (df_test_agg)

    col2              col3
id                        
1      1   [123, 234, 345]
2      1  [456, 1243, 346]
3      0   [888, 999, 777]

所需的输出应该是(理想情况下在 Pandas 中一步到位):

    col2              col3
id                        
1      1            [123, 234]
2      1            [456]
3      0            []

////////////////////////////////////////////////////////////////////////////////////

编辑 - 试用 ColdSpeed 的解决方案

df_test = pd.DataFrame({'id':[1, 1, 1, 2, 2, 2, 3, 3, 3], 'col2':[1, 1, 0, 1, 0, 0, 0, 0, 0], 'col3':[123, 234, 345, 456, 1243, 346, 888, 999, 777]})

print (df_test)

df_test_agg = (df_test.where(df_test.col2 > 0)
    .assign(id=df_test.id)
    .groupby('id')
    .agg({'col2': 'max', 'col3': lambda x: x.dropna().tolist()}))

print (df_test_agg)

   id  col2  col3
0   1     1   123
1   1     1   234
2   1     0   345
3   2     1   456
4   2     0  1243
5   2     0   346
6   3     0   888
7   3     0   999
8   3     0   777
    col2            col3
id                      
1    1.0  [123.0, 234.0]
2    1.0         [456.0]
3    NaN              []

////////////////////////////////////////////////////////////////////////////////////

编辑了原始帖子以呈现更多场景。

最佳答案

你可以预先过滤,然后使用groupby:

df_test.query('col2 > 0').groupby('id').agg({'col2': 'max', 'col3': list})

    col2        col3
id                  
1      1  [123, 234]
2      1       [456]

这里需要注意的是,如果一个组只有零,则该组将在结果中丢失。因此,要解决此问题,您可以使用 where 进行屏蔽:

(df_test.where(df_test.col2 > 0)
        .assign(id=df_test.id)
        .groupby('id')
        .agg({'col2': 'max', 'col3'lambda x: x.dropna().tolist()}))

    col2            col3
id                      
1    1.0  [123.0, 234.0]
2    1.0         [456.0]

要处理“col2”中的 0 个组,我们可以使用

(df.assign(col3=df.col3.where(df.col2.astype(bool)))
   .groupby('id')
   .agg({'col2':'max', 'col3': lambda x: x.dropna().astype(int).tolist()}))

    col2        col3
id                  
1      1  [123, 234]
2      1       [456]
3      0          []

关于python - 根据条件将列值转换为列表的列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54470907/

相关文章:

python - 基于月份提取 pandas 数据框的子集

python - 基于最频繁值的子集

python - cv2.groupRectangles 返回一个 len=1 的数组

python - Kmeans 返回的集群可视化

python - 将装饰器的函数传递给 Python RQ

r - 将交互式 Python Bokeh 图传输到 Shiny

python - 使用 pandas 时 Discord.gateway 警告 "Shard ID None heartbeat blocked for more than 10 seconds."

python - 使用 xarray (pcolormesh) 绘制 2D 数据,同时保持纵横比

c# - 你会分享你的想法如何从嵌入式 Python.Net 调用 python 命令吗?

python - 如何在 2d python 列表中找到最大数