【问题标题】:Get summary data columns in new pandas dataframe from existing dataframe based on other column-ID根据其他列 ID 从现有数据框中获取新熊猫数据框中的汇总数据列
【发布时间】:2020-04-19 15:56:45
【问题描述】:

我想汇总数据框中的数据并将新列添加到另一个数据框中。我的数据包含带有 ID 号的公寓,并且它具有公寓中每个房间的表面和体积值。我想要的是有一个数据框来总结这一点,并给我每个公寓的总面积和体积。原始数据框有两个条件:

Two conditions:
- the dataframe can contain empty cells
- when the values of surface or volume are equal for all of the rows within that ID 
(so all the same values for the same ID), then the data (surface, volumes) is not 
summed but one value/row is passed to the new summary column (example: 'ID 4')(as 
this could be a mistake in the original dataframe and the total surface/volume was 
inserted for all the rooms by the government-employee)

初始数据帧“数据”:

print(data)

    ID  Surface  Volume
0    2     10.0    25.0
1    2     12.0    30.0
2    2     24.0    60.0
3    2      8.0    20.0
4    4     84.0   200.0
5    4     84.0   200.0
6    4     84.0   200.0
7   52      NaN     NaN
8   52     96.0   240.0
9   95      8.0    20.0
10  95      6.0    15.0
11  95     12.0    30.0
12  95     30.0    75.0
13  95     12.0    30.0

'df' 的期望输出

print(df)
    ID  Surface  Volume
0    2     54.0   135.0
1    4     84.0   200.0  #-> as the values are the same for each row of this ID in the original data, the sum is not taken, but only one of the rows is passed (see the second condition)
2   52     96.0   240.0
3   95     68.0   170.0

试用过的代码:

import pandas as pd

import numpy as np



df = pd.DataFrame({"ID": [2,4,52,95]})



data = pd.DataFrame({"ID":  [2,2,2,2,4,4,4,52,52,95,95,95,95,95],
                
                "Surface":  [10,12,24,8,84,84,84,np.nan,96,8,6,12,30,12],
                 
                 "Volume":  [25,30,60,20,200,200,200,np.nan,240,20,15,30,75,30]})


print(data)




#Tried something, but no idea how to do this actually:

df["Surface"] = data.groupby("ID").agg(sum)

df["Volume"] = data.groupby("ID").agg(sum)
print(df)

【问题讨论】:

    标签: python pandas group-by


    【解决方案1】:

    这里有两个必要条件 - 首先通过 GroupBy.transformDataFrameGroupBy.nunique 分别测试每列的每个组的唯一值,然后通过 eq1 进行比较,然后是第二个条件 - 它使用了 DataFrame.duplicated每列加上ID 列。

    通过& 链接两个掩码以获取按位AND 并通过NaNs 通过DataFrame.mask 和最后一个聚合sum 替换匹配值:

    cols = ['Surface','Volume']
    m1 = data.groupby("ID")[cols].transform('nunique').eq(1)
    m2 = data[cols].apply(lambda x: x.to_frame().join(data['ID']).duplicated())
    
    df = data[cols].mask(m1 & m2).groupby(data["ID"]).sum().reset_index()
    print(df)
       ID  Surface  Volume
    0   2     54.0   135.0
    1   4     84.0   200.0
    2  52     96.0   240.0
    3  95     68.0   170.0
    

    如果需要由聚合总和值填充的​​新列,请使用GroupBy.transform

    cols = ['Surface','Volume']
    m1 = data.groupby("ID")[cols].transform('nunique').eq(1)
    m2 = data[cols].apply(lambda x: x.to_frame().join(data['ID']).duplicated())
    
    data[cols] = data[cols].mask(m1 & m2).groupby(data["ID"]).transform('sum')
    print(data)
        ID  Surface  Volume
    0    2     54.0   135.0
    1    2     54.0   135.0
    2    2     54.0   135.0
    3    2     54.0   135.0
    4    4     84.0   200.0
    5    4     84.0   200.0
    6    4     84.0   200.0
    7   52     96.0   240.0
    8   52     96.0   240.0
    9   95     68.0   170.0
    10  95     68.0   170.0
    11  95     68.0   170.0
    12  95     68.0   170.0
    13  95     68.0   170.0
    

    【讨论】:

    • 这个操作正是我的意思(打印的数据框中只缺少索引)。我还可以将新数据从数据帧“数据”立即传递到现有数据帧“df”还是在此之后需要一些东西 -> df['Surface'] = data['Surface']?
    • 您是否对基于此问题的下一个问题有想法/建议(它是关于汇总加权平均列)? -> stackoverflow.com/questions/61302339/…
    • @Matthi9000 - 答案似乎很好,使用它;)
    猜你喜欢
    • 2017-01-14
    • 2019-12-09
    • 1970-01-01
    • 1970-01-01
    • 2021-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多