в чем разница между .loc или без него при использовании groupby + transform в Pandas

Я новичок в питоне. вот вопрос, который у меня есть, который действительно странный для меня.

Простой фрейм данных выглядит так:

a1=pd.DataFrame({'Hash':[1,1,2,2,2,3,4,4],
                 'Card':[1,1,2,2,3,3,4,4]})

Мне нужно сгруппировать a1 по хэшу, вычислить, сколько строк в каждой группе, а затем добавить один столбец в a1, чтобы указать номера строк. Итак, я хочу использовать groupby + transform.

Когда я использую:

a1['CustomerCount']=a1.groupby(['Hash']).transform(lambda x: x.shape[0])

Результат правильный:

   Card  Hash  CustomerCount
0     1     1              2
1     1     1              2
2     2     2              3
3     2     2              3
4     3     2              3
5     3     3              1
6     4     4              2
7     4     4              2

Но когда я использую:

a1.loc[:,'CustomerCount']=a1.groupby(['Hash']).transform(lambda x: x.shape[0])

Результат:

   Card  Hash  CustomerCount
0     1     1            NaN
1     1     1            NaN
2     2     2            NaN
3     2     2            NaN
4     3     2            NaN
5     3     3            NaN
6     4     4            NaN
7     4     4            NaN

Итак, почему это происходит?

Насколько мне известно, loc и iloc (например, a1.loc[:,'CustomerCount']) лучше, чем ничего (например, a1['CustomerCount']), поэтому обычно рекомендуется использовать loc и iloc. Но почему это происходит?

Кроме того, я много раз пробовал использовать loc и iloc для создания нового столбца в одном фрейме данных. Они обычно работают. Так это как-то связано с groupby + transform?


person Feng Chen    schedule 05.06.2018    source источник


Ответы (1)


Разница заключается в том, как loc обрабатывает назначение объекта DataFrame одному столбцу. Когда вы назначили DataFrame столбцам Card, он попытался выровнять индекс и имя столбца. Столбцы не выстроились, и вы получили NaNs. При назначении через прямой доступ к колонке определил, что это одна колонка для другой и просто сделал это.

Уменьшить до одного столбца

Вы можете решить эту проблему, уменьшив результат операции groupby всего до одного столбца, что позволит упростить решение.

a1.loc[:,'CustomerCount'] = a1.groupby(['Hash']).Card.transform('size')
a1

   Hash  Card  CustomerCount
0     1     1              2
1     1     1              2
2     2     2              3
3     2     2              3
4     2     3              3
5     3     3              1
6     4     4              2
7     4     4              2

Переименуйте столбец

На самом деле не делайте этого, другой ответ намного проще

a1.loc[:, 'CustomerCount'] = a1.groupby('Hash').transform(len).rename(
    columns={'Card': 'CustomerCount'})
a1

pd.factorize и np.bincount

Что бы я на самом деле сделал

f, u = pd.factorize(a1.Hash)
a1['CustomerCount'] = np.bincount(f)[f]
a1

Или встроенное копирование

a1.assign(CustomerCount=(lambda f: np.bincount(f)[f])(pd.factorize(a1.Hash)[0]))

   Hash  Card  CustomerCount
0     1     1              2
1     1     1              2
2     2     2              3
3     2     2              3
4     2     3              3
5     3     3              1
6     4     4              2
7     4     4              2
person piRSquared    schedule 05.06.2018