удалить NaN, если только значение уже существует в соответствующих панах идентификаторов - PullRequest
0 голосов
/ 13 ноября 2018

У меня есть этот фрейм данных

 Id,ProductId,Product
  1,100,a
  1,100,x
  1,100,NaN
  2,150,NaN
  3,150,NaN
  4,100,a
  4,100,x
  4,100,NaN

Здесь я хочу удалить некоторые строки, содержащие NaN, и некоторые, которые я не хочу удалять. Критерии удаления следующие. Я хочу удалить только те строки NaN, чей Id уже содержит значение в столбцах Product. например, здесь Id1 уже имеет значение в столбцах Product и все еще содержит NaN, поэтому я хочу удалить эту строку. Но для id2 существует только NaN в столбце Product. Так что я не хочу удалять это. Точно так же и для Id3, в столбцах Product есть только значения NaN, и я хочу сохранить это значение тоже.

Окончательный вывод будет выглядеть так

Id,ProductId,Product
1,100,a
1,100,x
2,150,NaN
3,150,NaN
4,100,a
4,100,x

Ответы [ 4 ]

0 голосов
/ 13 ноября 2018

Вы можете сгруппировать фрейм данных по Id и удалить NaN, если в группе более одного элемента:

>> df.groupby(level='Id', group_keys=False
             ).apply(lambda x: x.dropna() if len(x) > 1 else x)

    ProductId Product
Id                   
1         100       a
1         100       x
2         150     NaN
3         150     NaN
4         100       a
4         100       x
0 голосов
/ 13 ноября 2018

Используйте groupby + transform с параметром count, а затем логическое индексирование с использованием isnull из Product столбца как:

count = df.groupby('Id')['Product'].transform('count')
df = df[~(count.ne(0) & df.Product.isnull())]

print(df)
   Id  ProductId Product
0   1        100       a
1   1        100       x
3   2        150     NaN
4   3        150     NaN
5   4        100       a
6   4        100       x
0 голосов
/ 13 ноября 2018

Не используйте groupby, если существует альтернатива, потому что медленно.

vals = df.loc[df['Product'].notnull(), 'Id'].unique()
df = df[~(df['Id'].isin(vals) & df['Product'].isnull())]
print (df)
   Id  ProductId Product
0   1        100       a
1   1        100       x
3   2        150     NaN
4   3        150     NaN
5   4        100       a
6   4        100       x

Объяснение :

Сначала получите все Id с некоторыми не пропущенными значениями:

print (df.loc[df['Product'].notnull(), 'Id'].unique())
[1 4]

Затем проверьте эти группы с отсутствующими значениями:

print (df['Id'].isin(vals) & df['Product'].isnull())
0    False
1    False
2     True
3    False
4    False
5    False
6    False
7     True
dtype: bool

Инвертировать логическую маску:

print (~(df['Id'].isin(vals) & df['Product'].isnull()))
0     True
1     True
2    False
3     True
4     True
5     True
6     True
7    False
dtype: bool

И последний фильтр по boolean indexing:

print (df[~(df['Id'].isin(vals) & df['Product'].isnull())])
   Id  ProductId Product
0   1        100       a
1   1        100       x
3   2        150     NaN
4   3        150     NaN
5   4        100       a
6   4        100       x
0 голосов
/ 13 ноября 2018

Рассчитать группы (Id), где все значения (Product) равны нулю, затем удалить необходимые строки с помощью логического индексирования с помощью loc accessor:

nulls = df.groupby('Id')['Product'].apply(lambda x: x.isnull().all())
nulls_idx = nulls[nulls].index

df = df.loc[~(~df['Id'].isin(nulls_idx) & df['Product'].isnull())]

print(df)

   Id  ProductId Product
0   1        100       a
1   1        100       x
3   2        150     NaN
4   3        150     NaN
5   4        100       a
6   4        100       x
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...