【问题标题】:Check if value of a column is seen for the first time in the group检查是否在组中第一次看到列的值
【发布时间】:2021-05-16 16:55:40
【问题描述】:

我想向 DataFrame 添加一个新的布尔列,以指示给定列的值是否第一次出现在 groupby 组中。

我的 DataFrame 是这样的:

    UserID  Value
0     1955     30
1     1955     40
2     1955     30
3     1956     30
4     1957     30
5     1957     50
6     1958     30
7     1958     50
8     1958     30
9     1958     30

我想得到这个:

    UserID  Value  IsNewValue
0     1955     30        True
1     1955     40        True
2     1955     30       False
3     1956     30        True
4     1957     30        True
5     1957     50        True
6     1958     30        True
7     1958     30       False
8     1958     30       False
9     1958     30       False

请务必注意,数据集已按用户 ID 和时间戳(此处未显示)排序,我无法更改此排序。

我想出了这段代码,虽然效率极低:

def is_new(group, col):
  seen = []
  ret = []
  for i in range(len(group)):
    ret.append(group[col].iloc[i] not in seen)
    seen.append(group[col].iloc[i])
  group[f'IsNew{col}'] = ret
  return group

for col in ['ValueA', 'ValueB', 'ValueC']:
  dataset = dataset.groupby('UserID').apply(lambda x: is_new(x, col))

我想知道如何重写代码并使其更高效,可能使用 Pandas 的窗口函数或一些 numpy 功能。

【问题讨论】:

    标签: python pandas numpy pandas-groupby


    【解决方案1】:

    使用:duplicated 并否定结果

    df['IsNewValue'] = ~df.duplicated(['UserID', 'Value'])
    

       UserID  Value  IsNewValue
    0    1955     30        True
    1    1955     40        True
    2    1955     30       False
    3    1956     30        True
    4    1957     30        True
    5    1957     50        True
    6    1958     30        True
    7    1958     50        True
    8    1958     30       False
    9    1958     30       False
    

    【讨论】:

      【解决方案2】:

      除了 sushanth 的解决方案(这似乎回答了 OP 关于使用 PANDAS 函数的问题),您还可以通过使用 itertuples() 迭代 df 来手动计算值。

      这是我的实现:

      import pandas as pd
      
      UserID = [1955,1955,1955,1956,1957,1957,1958,1958,1958,1958]
      Value = [30,40,30,30,30,50,30,50,30,30]
      
      df = pd.DataFrame(list(zip(UserID, Value)), columns = ["UserID", "Value"])
      
      def createDuplicateCol(df):
          currentUserID = None
          values = set()
          newCol = []
          for row in df.itertuples():
              newColVal = True
              if row.UserID == currentUserID:
                  if row.Value in values:
                      newColVal = False
                  else:
                      values.add(row.Value)
              else:
                  currentUserID = row.UserID
                  values = set()
                  values.add(row.Value)
      
              newCol.append(newColVal)
      
          df["IsNewValue"] = newCol
      
          return df
      
      df = createDuplicateCol(df)
      

      此方法使用集合来存储值并检查重复项,因为它们已针对该类型的操作进行了优化。它还利用排序排列来仅存储给定组所需的值。在对 OP 的数据进行一些基本分析后,我发现性能与使用 df.duplicated 方法相当。但是,对于较大的数据帧,性能可能会发生变化。

      【讨论】:

        【解决方案3】:

        这是一种方法:

        df['IsNewValue'] = df.sort_values('Value').groupby('UserID')['Value'].transform(lambda x: x.diff().ne(0))
        

        【讨论】:

          猜你喜欢
          • 2013-05-29
          • 1970-01-01
          • 1970-01-01
          • 2018-07-25
          • 1970-01-01
          • 2020-01-09
          • 1970-01-01
          • 1970-01-01
          • 2020-07-23
          相关资源
          最近更新 更多