Расширение серии Pandas в dataframe с помощью уникальных значений

#python #pandas #dataframe

#python #панды #фрейм данных

Вопрос:

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

Первая, более простая версия — если я начну с этого:

 Idx  Tag
0    A
1    B
2    A
3    C
4    B
 

Я хотел бы получить что-то вроде этого, где уникальными значениями в начальном ряду являются значения столбцов здесь (могут быть 1 и 0, логические значения и т.д.).:

 Idx  A   B   C
0    1   0   0
1    0   1   0
2    1   0   0
3    0   0   1
4    0   1   0
 

Вторая, более продвинутая версия — если у меня есть значения, связанные с каждой записью, сохраняя их и заполняя остальную часть матрицы заполнителем (0, NaN, что-то еще), например, начиная с этого:

 Idx  Tag  Val
0    A    5
1    B    2
2    A    3
3    C    7
4    B    1
 

И в конечном итоге с этим:

 Idx  A   B   C
0    5   0   0
1    0   2   0
2    3   0   0
3    0   0   7
4    0   1   0
 

Каков питонический способ сделать это?

Ответ №1:

Вот как это сделать, используя pandas.get_dummies() который был разработан специально для этого (часто называемый «one-hot-encoding» в ML). Я сделал это шаг за шагом, чтобы вы могли видеть, как это делается 😉

 >>> df
   Idx Tag  Val
0    0   A    5
1    1   B    2
2    2   A    3
3    3   C    7
4    4   B    1

>>> pd.get_dummies(df['Tag'])
   A  B  C
0  1  0  0
1  0  1  0
2  1  0  0
3  0  0  1
4  0  1  0

>>> pd.concat([df[['Idx']], pd.get_dummies(df['Tag'])], axis=1)
   Idx  A  B  C
0    0  1  0  0
1    1  0  1  0
2    2  1  0  0
3    3  0  0  1
4    4  0  1  0

>>> pd.get_dummies(df['Tag']).to_numpy()
array([[1, 0, 0],
       [0, 1, 0],
       [1, 0, 0],
       [0, 0, 1],
       [0, 1, 0]], dtype=uint8)

>>> df2[['Val']].to_numpy()
array([[5],
       [2],
       [3],
       [7],
       [1]])

>>> pd.get_dummies(df2['Tag']).to_numpy() * df2[['Val']].to_numpy()
array([[5, 0, 0],
       [0, 2, 0],
       [3, 0, 0],
       [0, 0, 7],
       [0, 1, 0]])

>>> pd.DataFrame(pd.get_dummies(df['Tag']).to_numpy() * df[['Val']].to_numpy(), columns=df['Tag'].unique())
   A  B  C
0  5  0  0
1  0  2  0
2  3  0  0
3  0  0  7
4  0  1  0

>>> pd.concat([df, pd.DataFrame(pd.get_dummies(df['Tag']).to_numpy() * df[['Val']].to_numpy(), columns=df['Tag'].unique())], axis=1)
   Idx Tag  Val  A  B  C
0    0   A    5  5  0  0
1    1   B    2  0  2  0
2    2   A    3  3  0  0
3    3   C    7  0  0  7
4    4   B    1  0  1  0
 

Комментарии:

1. Спасибо! pd.get_dummies это ключ, я не знал, что такая функция существует!

2. Это действительно хорошо, я знаю!

3. Вам нужно знать о. pandas.Series.str.get_dummies() Здесь это неприменимо, но когда вам это нужно, это настоящая находка.

Ответ №2:

Основываясь на ответе @user17242583, нашел довольно простой способ сделать это, используя pd.get_dummies в сочетании с DataFrame.multiply :

 >>> df
   Tag  Val
0   A   5
1   B   2
2   A   3
3   C   7
4   B   1

>>> pd.get_dummies(df['Tag'])
    A   B   C
0   1   0   0
1   0   1   0
2   1   0   0
3   0   0   1
4   0   1   0

>>> pd.get_dummies(df['Tag']).multiply(df['Val'], axis=0)
    A   B   C
0   5   0   0
1   0   2   0
2   3   0   0
3   0   0   7
4   0   1   0