【问题标题】:Multiple conditions driven by series系列驱动的多个条件
【发布时间】:2021-07-29 22:00:36
【问题描述】:

我有一个数据框来存储一个人的居住地,它看起来像这样:

SECT PAD ROOM PERSON
1 A 101 PERSON1
1 A 102 PERSON2
1 B 101 PERSON3
2 A 103 PERSON4
2 C 102 PERSON5

我还有另一个数据框,它指定了使该住房单元与众不同的所有 SECT/PAD/ROOM 组合(注意:如果不存在 start_room 和 end_room,则意味着该 sect/pad 中的所有房间都是特殊的):

SECT PAD ROOM START_ROOM END_ROOM
1 A 101 100 104
1 A 102
1 C 101 105 500

有没有办法使用“特殊”数据框识别所有“特殊”住房单元,然后在第一个数据框中添加一个新列来标记它们。 “特殊”数据框要大得多,如果我必须手动执行条件 .loc 语句来识别所有特殊住房单元,那将需要很长时间。我希望能够以编程方式匹配它们

【问题讨论】:

  • 请包括您的预期输出。
  • 基本上,我正在寻找第一个表中与第二个表中的一个条件匹配的所有人。结果将是 PERSON 1 和 PERSON 2 的 df。
  • 但是对于 SECT 1 PAD A,您在第二个 DataFrame 中有 2 行。那么只有 100 到 104 间是特价房还是所有房间都是特价房?

标签: python pandas dataframe


【解决方案1】:

所以我会将第一个数据帧合并到特殊数据帧上,然后添加一个具有特殊条件的列

df_person = pd.DataFrame({'SECT': [1, 1, 1, 2, 2], 
                         'PAD': ['A', 'A', 'B', 'A', 'C'],
                         'ROOM': [101, 102, 101, 103, 102],
                         'PERSON': ['PERSON1', 'PERSON2', 'PERSON3', 'PERSON4', 'PERSON5']})
df_special = pd.DataFrame({'SECT':[1, 1, 1],
                          'PAD':['A', 'A', 'C'],
                          'ROOM':[101, 102, 101],
                          'START_ROOM': [100, '', 105],
                          'END_ROOM': [104, '', 500]})

df_merged = df_person.merge(df_special, on=['SECT', 'PAD', 'ROOM'], how='left')
rows_to_update1 = df_merged[(df_merged['START_ROOM']=='')&
                           (df_merged['END_ROOM']=='')].index
rows_to_update2 = df_merged[((df_merged['ROOM'].astype('int32')>=pd.to_numeric(df_merged['START_ROOM'], errors='coerce'))&
                           (df_merged['ROOM'].astype('int32')<=pd.to_numeric(df_merged['END_ROOM'], errors='coerce')))].index
df_merged['IS_SPECIAL'] = False
df_merged.loc[rows_to_update1.union(rows_to_update2), 'IS_SPECIAL'] = True

这是一个棘手的问题,因为您的 START_ROOM 和 END_ROOM 是字符串和整数的混合。我建议不要将这两列作为空字符串来表示所有房间都是特殊的。

【讨论】:

    【解决方案2】:

    由于空行意味着所有房间都是特殊的,您可以只用虚拟值(第一个 df 的最小值和最大值)填充它们,然后从合并的 DataFrame 中获取所需的结果。

    假设您的 DataFrame 是 df1df2,您可以这样做:

    df2["START_ROOM"] = df2["START_ROOM"].fillna(df1["ROOM"].min())
    df2["END_ROOM"] = df2["START_ROOM"].fillna(df1["ROOM"].max())
    
    merged = df1.merge(df2, on=["SECT", "PAD", "ROOM"], how="left")
    result = df1[df1["PERSON"].isin(merged.dropna()["PERSON"].tolist())]
    
    >>> result
       SECT PAD  ROOM   PERSON
    0     1   A   101  PERSON1
    1     1   A   102  PERSON2
    

    【讨论】:

      猜你喜欢
      • 2016-03-08
      • 1970-01-01
      • 2017-03-22
      • 1970-01-01
      • 1970-01-01
      • 2021-09-20
      • 2022-11-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多