【问题标题】:Pandas Dataframe Python | How to compare a cell with another cell of a copied dataframe?熊猫数据框 Python |如何将一个单元格与复制的数据帧的另一个单元格进行比较?
【发布时间】:2020-12-08 16:42:51
【问题描述】:

我有 2 个名称不同的相同数据帧(df_1 和 df_2)。

假设数据框有 2 列类别和时间。 例如。

Category Time
A 2020-02-02 05:05:05.0000
A 2020-02-02 06:06:06.0000
A 2020-02-02 07:07:07.0000
B 2020-02-02 05:05:05.0000
B 2020-02-02 06:06:06.0000
C 2020-02-02 05:05:05.0000
C 2020-02-02 06:06:06.0000

我想要以下 if 条件: 如果 df_1 的类别与 df_2 的类别匹配,那么在一个新的数据帧中(列:类别、开始时间、结束时间),如果是 A 类别,我想放置第一个日期时间(2020-02-02 05:05:05.0000 ) 在 endtime 列中的 starttime 和 last datetime (2020-02-02 07:07:07.0000)。

最终结果新数据框:

Category Start Time EndTime
A 2020-02-02 05:05:05.0000 2020-02-02 07:07:07.0000
B 2020-02-02 05:05:05.0000 2020-02-02 06:06:06.0000
C 2020-02-02 05:05:05.0000 2020-02-02 06:06:06.0000

我怎样才能做到这一点?请帮忙。

【问题讨论】:

    标签: python python-3.x pandas dataframe compare


    【解决方案1】:

    原始答案的解决方案

    pd.concat([df_1.groupby("CATEGORY").agg([min, max]),
               df_2.groupby("CATEGORY").agg([min, max])], 
            join="inner", axis=1).apply([min, max], axis=1)
        .rename(columns={"min":"START TIME", "max":"END TIME"})
    

    说明

    1. 首先,您按 CATEGORY 对每个 DataFrame 进行分组,以保持其每个值的最小值和最大值。这也会将索引设置为 CATEGORY。

      grouped_1 = df_1.groupby("CATEGORY").agg([min, max])
      grouped_2 = df_2.groupby("CATEGORY").agg([min, max])
      
    2. 然后,您执行内部连接以仅保留 df_1 和 df_2 中的 CATEGOries。默认情况下,内部连接是在索引上完成的,这就是我们在这里想要的(我们原始 DataFrame 中的列 CATEGORY)。您水平连接,得到 4 列:每行两个最小值和两个最大值。

      grouped_both = pd.concat([grouped_1, grouped_2], join="inner", axis=1)
      
    3. 您保留每行的最小值和最大值,并重命名列。

      final_df = grouped_both.apply([min, max], axis=1)
          .rename(columns={"min":"START TIME", "max":"END TIME"})
      

    注意:我假设您想合并两个 DataFrame 的第一个和最后一个时间戳。 如果你真的想要从 df_1 开始并从 df_2 结束,那将是一个稍微不同的解决方案。

    一个DataFrame并增加持续时间的解决方案

    如果我理解正确,那么你不需要复制原始的DataFrame。

    # Group the DataFrame by CATEGORY and keep the min and max values
    # We also need to get rid of the newly created MultiIndex level "TIME"
    joined_df = df_1.groupby("CATEGORY").agg([min, max])["TIME"]
    # Keep only rows where the min is different than the max
    joined_df = joined_df[joined_df["min"]!= joined_df["max"]]
    # Calculate the time deltas between min and max
    # then cast it to a number value of the minutes
    joined_df["DURATION"] = (joined_df[ "max"]- joined_df["min"]).astype('timedelta64[m]')
    # We rename the columns min and max
    joined_df = joined_df.rename(columns={"min":"START TIME", "max":"END TIME"})
    

    【讨论】:

    • 非常感谢,这使得事情在几个步骤中变得非常简单,无需 for 循环和 if 条件。有没有办法添加另一列(以分钟为单位的持续时间),时间戳的差异?我的方法:“2 个相同的数据帧”实际上是一个数据帧,另一个是复制的(df_1.copy())。这样做的目的是从一个获得第一个时间戳,从另一个获得最后一个时间戳。然后,在新数据帧中检查类别条目是否存在,如果不存在,则使用 df_1 的该行填充新数据帧,否则将结束时间替换为 df_2 中该迭代的当前时间戳。
    • 我刚刚编辑了我的答案。我不确定它是否正确满足了您评论中的需求,所以请告诉我。
    • 这完美地回答了我的问题!非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2021-03-02
    • 2022-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-29
    • 1970-01-01
    相关资源
    最近更新 更多