У меня есть pandas.DataFrame:

|   | col_1 | col_2 | col_3 | col_4 |
|:--|:------|:------|:------|:------|
| 0 |   1   |   2   |  NaN  |  NaN  |
| 1 |   3   |   4   |   5   |   6   |
| 2 |   2   |   6   |  NaN  |  NaN  |

Я должен преобразовать значения (1, 2, 3, 4, 5, 6) в столбцы и установить 1 для строк, если это значение в строке и 0 в противном случае:

|   | 1 | 2 | 3 | 4 | 5 | 6 |
|:--|:--|:--|:--|:--|:--|:--|
| 0 | 1 | 1 | 0 | 0 | 0 | 0 |
| 1 | 0 | 0 | 1 | 1 | 1 | 1 |
| 2 | 0 | 1 | 0 | 0 | 0 | 1 |

pd.get_dummies здесь не работает. Как я вижу, pd.get_dummies не может one_hot кодировать через все значения в столбцах информационного кадра

Как я могу этого добиться?

2
feeeper 21 Авг 2018 в 12:45

3 ответа

Лучший ответ

Один подход с broadcasting -

In [67]: df
Out[67]: 
     0    1    2    3
0  1.0  2.0  NaN  NaN
1  3.0  4.0  5.0  6.0
2  2.0  6.0  NaN  NaN

In [68]: constant_set = [1, 2, 3, 4, 5, 6]

In [69]: (df.values[:,:,None] == constant_set).any(1).astype(int)
Out[69]: 
array([[1, 1, 0, 0, 0, 0],
       [0, 0, 1, 1, 1, 1],
       [0, 1, 0, 0, 0, 1]])

# Dataframe output
In [73]: out = (df.values[:,:,None] == constant_set).any(1).astype(int)

In [74]: pd.DataFrame(out, columns=constant_set)
Out[74]: 
   1  2  3  4  5  6
0  1  1  0  0  0  0
1  0  0  1  1  1  1
2  0  1  0  0  0  1

Еще один с учетом эффективности памяти -

idx = np.searchsorted(constant_set, a)
out = np.zeros((len(df),len(constant_set)),dtype=int)
flattend_idx = idx + out.shape[1]*np.arange(len(idx))[:,None]
out.flat[flattend_idx[idx<len(constant_set)]] = 1
2
Divakar 21 Авг 2018 в 10:21

Вы также можете использовать функцию get_dummies следующим образом:

import numpy  as np
import pandas as pd

# The definition of your dataframe
df = pd.DataFrame({'col_1': [1, 3, 2],
                   'col_2': [2, 4, 6],
                   'col_3': [np.NaN, 5, np.NaN],
                   'col_4': [np.NaN, 6, np.NaN]}, dtype=float)

# Get dummies where you leave out the prefix
# This will ensure that all columns of the same value will get the same column name
df = pd.get_dummies(df, columns=['col_1', 'col_2', 'col_3', 'col_4'], prefix='')

# Initialise your result
result = pd.DataFrame()
# Use the groupby method to group on column name
for column, data in df.groupby(level=0, axis=1):
    # Merge data of same columns into one column
    result[column] = data.max(axis=1)

Итак, что мы здесь делаем, так это применяем get_dummies ко всем столбцам, что приводит к чему-то вроде

   _1.0  _2.0  _3.0  _2.0  _4.0  _6.0  _5.0  _6.0
0     1     1     0     1     0     0     0     0
1     0     0     1     0     1     1     1     1
2     0     1     0     1     0     1     0     1

Затем мы объединяем все столбцы с одинаковыми именами, чтобы получить желаемый результат

   _1.0  _2.0  _3.0  _4.0  _5.0  _6.0
0     1     1     0     0     0     0
1     0     0     1     1     1     1
2     0     1     0     0     0     1
2
Thijs van Ede 21 Авг 2018 в 11:10

Другой подход с использованием pd.melt():

# Set it up.
import numpy as np; import pandas as pd;
df = pd.DataFrame({'col_1': [1, 3, 2],
                   'col_2': [2, 4, 6],
                   'col_3': [np.NaN, 5, np.NaN],
                   'col_4': [np.NaN, 6, np.NaN]}, dtype=float)

(pd.get_dummies(                     # Pandas' one-hot function
    df.T.melt()                      # Flip DataFrame, then switch from wide to long format.
    .set_index('variable')['value']) # "variable' is the row name (id) in your orig DataFrame.
.groupby('variable')
.sum())                              # Coalesce same ids and add rows together.
1
user1717828 21 Авг 2018 в 16:30
51945917