Удаление дубликатов только внутри групп - PullRequest
0 голосов
/ 26 декабря 2018

Я хочу удалить дубликаты только в определенных подмножествах из фрейма данных.Под каждой «спецификацией» в столбце «A» я хочу отбросить дубликаты, но хочу сохранить дубликаты во всем фрейме данных (возможно иметь несколько строк под первой «спецификацией», которые совпадают со строками подвторой «spec», но под «spec» до следующей «spec» я хочу отбросить дубликаты)

Это фрейм данных

df

  A          B            C
  spec       first        second
  test       text1        text2
  act        text12       text13
  act        text14       text15
  test       text32       text33
  act        text34       text35
  test       text85       text86
  act        text87       text88
  test       text1        text2
  act        text12       text13
  act        text14       text15
  test       text85       text86
  act        text87       text88
  spec       third        fourth
  test       text1        text2
  act        text12       text13
  act        text14       text15
  test       text85       text86
  act        text87       text88
  test       text1        text2
  act        text12       text13
  act        text14       text15
  test       text85       text86
  act        text87       text88

иэто то, что я хочу:

df

  A          B            C
  spec       first        second
  test       text1        text2
  act        text12       text13
  act        text14       text15
  test       text32       text33
  act        text34       text35
  test       text85       text86
  act        text87       text88
  spec       third        fourth
  test       text1        text2
  act        text12       text13
  act        text14       text15
  test       text85       text86
  act        text87       text88

Я мог бы разделить фрейм данных на «маленькие» фреймы данных, а затем создать дубликаты для удаления цикла для каждого из «маленьких» фреймов данных,и, наконец, объединить их, но мне интересно, есть ли какое-либо другое решение.

Я также пытался и успешно:

dfList = df.index[df["A"] == "spec"].tolist()
dfList = np.asarray(dfList)
for dfL in dfList:
      idx = np.where(dfList == dfL)
      if idx[0][0]!=(len(dfList)-1):
            df.loc[dfList[idx[0][0]]:dfList[idx[0][0]+1]-1]
                     = df.loc[dfList[idx[0][0]]:dfList[idx[0][0]+1]-1].drop_duplicates()
      else:
            df.loc[dfList[idx[0][0]]:] = df.loc[dfList[idx[0][0]]:].drop_duplicates()

РЕДАКТИРОВАТЬ: я должен добавить это до конца:

df.dropna (how = 'all', inplace = True)

Но мне просто интересно, есть ли другое решение.

Ответы [ 3 ]

0 голосов
/ 26 декабря 2018

Другое возможное решение может быть ... Вы можете иметь счетчик и создать новый столбец из столбца A со значением счетчика, всякий раз, когда вы сталкиваетесь со спецификацией в значении столбца, вы увеличиваете значение счетчика.

counter = 0
def counter_fun(val):
    if val == 'spec': counter+=1
    return counter

df['new_col'] = df.A.apply(counter_fun)

Затем сгруппируйте на new_col и отбросьте дубликаты.

0 голосов
/ 26 декабря 2018

Использование groupby + duplicated:

df[~df.groupby(df.A.eq('spec').cumsum()).apply(lambda x: x.duplicated()).values]

       A       B       C
0   spec   first  second
1   test   text1   text2
2    act  text12  text13
3    act  text14  text15
4   test  text32  text33
5    act  text34  text35
6   test  text85  text86
7    act  text87  text88
13  spec   third  fourth
14  test   text1   text2
15   act  text12  text13
16   act  text14  text15
17  test  text85  text86
18   act  text87  text88

Подробности

Мы находим все строки в определенной записи «spec», используя cumsum.Метки группы:

df.A.eq('spec').cumsum()

0     1
1     1
2     1
3     1
4     1
5     1
6     1
7     1
8     1
9     1
10    1
11    1
12    1
13    2
14    2
15    2
16    2
17    2
18    2
19    2
20    2
21    2
22    2
23    2
Name: A, dtype: int64

Затем в этой серии выполняется группировка, и для каждой группы вычисляются дубликаты:

df.groupby(df.A.eq('spec').cumsum()).apply(lambda x: x.duplicated()).values

array([False, False, False, False, False, False, False, False,  True,
        True,  True,  True,  True, False, False, False, False, False,
       False,  True,  True,  True,  True,  True])

Из этого остается только сохранить тестроки, соответствующие «False» (то есть, не дублированы).

0 голосов
/ 26 декабря 2018

Это должно работать:

df2 = df.drop_duplicates(subset=['A', 'B','C'])
...