python - Pandas 分组,聚合两列并返回一列的最早开始日期

标签 python pandas csv

我正在尝试按 Pandas 中的 csv 文件进行分组(按一列:ID),以获得最早的开始日期和最晚的结束日期。然后我尝试按多列进行分组以获得值的总和。对于第二个 groupedby 数据框中的每个 ID,我想显示日期。

我正在加载 csv 以便对数据进行分组和聚合。

01) 首先我加载 csv

def get_csv():
        #Read csv file
        df = pd.read_csv('myFile.csv', encoding = "ISO-8859-1",parse_dates=['Start Date', 'End Date'])

        return df

02) 对列(ID 和站点)的数据进行分组和聚合

def do_stuff():
     df = get_csv()   
     groupedBy = df[df['A or B'].str.contains('AAAA')].groupby([df['ID'], df['Site'].fillna('Other'),]).agg({'Start Date': 'min', 'End Date': 'max', 'Value': 'sum'})

它按预期工作,我得到以下内容(示例):

enter image description here

03) 理想情况下,对于同一个 ID,我希望在“开始日期”列中显示最早的日期,在“结束日期”列中显示最新的日期。值的聚合效果非常好。我想要得到的是以下内容:

enter image description here

我不知道如何更改上面当前的代码。到目前为止我已经尝试过:

def do_stuff():
    df = get_csv()
    md = get_csv()

    minStart = md[md['A or B'].str.contains('AAAA')].groupby([md['ID']]).agg({'Start Date': 'min'})

    df['earliestStartDate'] = minStart

    groupedBy = df[df['A or B'].str.contains('AAAA')].groupby([df['ID'], df['Site'].fillna('Other'),df['earliestStartDate']]).agg({'Start Date': 'min', 'End Date': 'max', 'Value': 'sum'})

失败了,还尝试将上面的内容更改为:

def do_stuff():
    df = get_csv()
    md = get_csv()

    df['earliestStartDate'] = md.loc[ md['ID'] == df['ID'], 'Start Date'].min()

    groupedBy = df[df['A or B'].str.contains('AAAA')].groupby([df['ID'], df['Site'].fillna('Other'),df['earliestStartDate']]).agg({'Start Date': 'min', 'End Date': 'max', 'Value': 'sum'})

理想情况下,我只需更改 groupedBy 中的某些内容,而不必读取 csv 两次并聚合数据两次。那可能吗?如果没有,我可以更改什么以使脚本正常工作?我正在尝试随机测试以获得更多 Pandas 和 Python 经验。

我猜我必须在这里创建两个数据帧。用于获取所有所需列的groupedby 数据(以及值的总和)。第二个用于获取每个 ID 的最早开始日期和最晚结束日期。然后我需要找到一种方法来连接两个数据帧。这是一个好的结果还是您认为有更简单的方法可以实现这一目标?

UPD:我创建了两个数据框的代码(不确定这是否是正确的解决方案)如下:

#Read csv file
df = pd.read_csv('myFile.csv', encoding = "ISO-8859-1",mangle_dupe_cols=True, parse_dates=['Start Date', 'End Date'])
md = pd.read_csv('myFile.csv', encoding = "ISO-8859-1",mangle_dupe_cols=True, parse_dates=['Start Date', 'End Date'])


#Calculate the Clean Value
df['Clean Cost'] = (df['Value'] - df['Value2']) #.apply(lambda x: round(x,0))

#Get the min/max Dates
minMaxDates = md[md['Random'].str.contains('Y')].groupby([md['ID']]).agg({'Start Date': 'min', 'End Date': 'max'})

#Group by and aggregate (return Earliest Start Date, Latest End Date and SUM of the Values)
groupedBy = df[df['Random'].str.contains('Y')].groupby([df['ID'], df['Site'].fillna('Other')]).agg({'Start Date': 'min', 'End Date': 'max', 'Value': 'sum', 'Value2': 'sum', 'Clean Cost': 'sum'})

如果我打印两个数据帧,我会得到以下结果:

minMaxDates

enter image description here

如果我打印 df.head(),我会得到以下结果:

  ID A or B Start Date   End Date  Value  Site  Value2 Random                                                 alse.

0 45221 AAAA 2017-12-30 2017-09-30 14 S111 7 Y 1 45221 AAAA 2017-01-15 2017-09-30 15 S222 7 Y 2 85293 BBBB 2017-05-12 2017-07-24 29 S111 3 Y 3 85293 AAAA 2017-03-22 2017-10-14 32 S222 4 Y 4 45221 AAAA 2017-01-15 2017-09-30 30 S222 7 Y

此处给出了该文件的链接:LINK

最佳答案

我认为你需要transform :

df = pd.read_csv('sampleBionic.csv')
print (df)
      ID A or B  Start Date    End Date  Value  Site  Value2 Random
0  45221   AAAA  12/30/2017  09/30/2017     14  S111       7      Y
1  45221   AAAA  01/15/2017  09/30/2017     15  S222       7      Y
2  85293   BBBB  05/12/2017  07/24/2017     29  S111       3      Y
3  85293   AAAA  03/22/2017  10/14/2017     32  S222       4      Y
4  45221   AAAA  01/15/2017  09/30/2017     30  S222       7      Y

groupedBy = (df[df['A or B'].str.contains('AAAA')]
                            .groupby([df['ID'], df['Site'].fillna('Other'),])
                            .agg({'Start Date': 'min', 'End Date': 'max', 'Value': 'sum'}))
print (groupedBy)    
            Start Date    End Date  Value
ID    Site                               
45221 S111  12/30/2017  09/30/2017     14
      S222  01/15/2017  09/30/2017     45
85293 S222  03/22/2017  10/14/2017     32

g = groupedBy.groupby(level=0)              
groupedBy['Start Date'] = g['Start Date'].transform('min') 
groupedBy['End Date'] = g['End Date'].transform('max')
print (groupedBy)
            Start Date    End Date  Value
ID    Site                               
45221 S111  01/15/2017  09/30/2017     14
      S222  01/15/2017  09/30/2017     45
85293 S222  03/22/2017  10/14/2017     32

关于python - Pandas 分组,聚合两列并返回一列的最早开始日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47041123/

相关文章:

python - Numpy的where函数和长度报错信息

Python字典

python - 在不复制的情况下选择列的子集

python - 使用 pandas read_csv 检测导入 csv 文件的 header 分隔符

javascript - 使用 Javascript 读取 Csv 文件

mysql - 将 Json 字段从 csv 导入 MySQL 5.7.19-0ubuntu0.16.04.1

python - AF_INET 和 PF_INET 常量有什么区别?

python - Pandas:使用重复值进行透视

python - pandas 中多索引列的成对减法

python - 通过用向量化替换 lambda x 来增强排序函数的性能