Python: 是否有仅计算日期的解决方案(pivot 或 groupby)

Python: Is there an Solution (pivot or groupby) to count dates only

是否有简单的解决方案来获取以下信息?我是 python 和 DataFrames 的新手,目前我无法解决这个问题。

import pandas as pd
from datetime import date

d1 = date(2020,11,23)
d2 = date(2020,11,24)
d3 = date(2020,11,25)

df_test = pd.DataFrame({'Area': ['Area_A', 'Area_A', 'Area_B'], 
                        'Sub_Area': ['Area_A1', 'Area_A2', 'Area_B1'],
                        'Milestone_1': [d1, d2, '-'], 
                        'Milestone_2': [d3, '-', '-']}) 
df_test 
------------------------------------
     Area Sub_Area Milestone_1 Milestone_2
0  Area_A  Area_A1  2020-11-23  2020-11-25
1  Area_A  Area_A2  2020-11-24           -
2  Area_B  Area_B1           -           -
------------------------------------

我需要估算每个区域的最新里程碑信息:

  1. 分区数量,
  2. 每个分区的近期里程碑和
  3. 每个区域最近的里程碑数量。

最终的 table 或数据框应如下所示:

------------------------------------
     Area  Sum_of_Sub_Area Sum_of_Milestone_1 Sum_Milestone_2
0  Area_A  2               2                  1
1  Area_B  1               0                  0
------------------------------------

有人可以帮我吗?

我第一次尝试 pivot_table 没有提供正确的解决方案,因为我只需要计算日期。 Area_BMilestone 中没有日期:

df_test.pivot_table(values=['Sub_Area', 'Milestone_1', 'Milestone_2'], 
                                      index=['Area'],
                                      aggfunc=['count'],
                                      fill_value=0)

------------------------------------
             count
       Milestone_1 Milestone_2 Sub_Area
Area
Area_A           2           2        2
Area_B           1           1        1
------------------------------------

一切都与进入 agg()

的数据的一致性有关
  1. - 替换为 np.nan 然后确保 里程碑 列仍然是 datetime64
  2. 简单 groupby()agg()count 得到你想要的
from datetime import date

d1 = date(2020,11,23)
d2 = date(2020,11,24)
d3 = date(2020,11,25)

df_test = pd.DataFrame({'Area': ['Area_A', 'Area_A', 'Area_B'], 
                        'Sub_Area': ['Area_A1', 'Area_A2', 'Area_B1'],
                        'Milestone_1': [d1, d2, '-'], 
                        'Milestone_2': [d3, '-', '-']}) 

dfc = df_test.replace({"-":np.nan}).astype({c:"datetime64" for c in df_test.columns if "Mile" in c})\
    .groupby("Area").agg({"Milestone_1":"count","Milestone_2":"count"})

print(dfc.to_string())

输出

        Milestone_1  Milestone_2
Area                            
Area_A            2            1
Area_B            0            0

我使用了除 pivot 之外的其他方法 -

areas = df_test["Area"].unique().tolist()
est_by_area = pd.DataFrame(index = areas)
est_by_area["Sum_of_Sub_Area"] = df_test["Area"].value_counts().to_frame()
df_test[["Milestone_1", "Milestone_2"]] = df_test[["Milestone_1", "Milestone_2"]].replace("-", np.nan)
est_by_area["Sum_of_Milestone_1"] = df_test.groupby("Area")["Milestone_1"].count().to_frame()
est_by_area["Sum_of_Milestone_2"] = df_test.groupby("Area")["Milestone_2"].count().to_frame()

我将回顾一下我在这里所做的事情:

首先,我创建了唯一的区域列表。 比我创建名为“est_by_area”的新数据框,而它的索引是我之前创建的区域列表。 之后,我将 value_counts() 方法分配给“Sum_of_Sub_Area”列,value_counts() 方法为您提供唯一值和它们出现的次数。 之后我遇到了日期问题,我有 2 列“Milestone_1”和“Milestone_2”,混合日期和字符串包含“-”表示空日期。 我在这里所做的是将空日期转换为 np.nan,因此当我在其上使用方法时,它不会计算空日期(“-”)。 最后,我按“区域”列对 df 进行分组,计算每列有值的次数并将其分配给我们的新数据框。

结果:

    Sum_of_Sub_Area     Sum_of_Milestone_2
Area_A  2               1
Area_B  1               0

希望对您有所帮助。