Я почти уверен, что вы столкнулись с проблемами с памятью, потому что str.get_dummies возвращает массив, полный единиц и 0, с типом данных np.int64
.Это сильно отличается от поведения pd.get_dummies , которое возвращает массив значений типа данных uint8
.
Это, похоже, известная проблема .Однако за прошедший год не было ни обновлений, ни исправлений.Проверка исходного кода для str.get_dummies действительно подтвердит, что он возвращает np.int64
.
8-разрядное целое число займет 1 байт памяти, а 64-разрядное целое число будетзанимают 8 байтов.Я надеюсь, что проблем с памятью можно избежать, найдя альтернативный способ быстрого кодирования Col2
, который обеспечивает вывод всех 8-битных целых чисел.
Вот мой подход, начиная с вашего примера:
df = pd.DataFrame({'Col1': ['X', 'Y', 'X'],
'Col2': ['a,b,c', 'a,b', 'b,d']})
df
Col1 Col2
0 X a,b,c
1 Y a,b
2 X b,d
- Так как
Col1
содержит простые строки без разделителей, мы можем легко в горячем виде кодировать их, используя pd.get_dummies:
df = pd.get_dummies(df, columns=['Col1'])
df
Col2 Col1_X Col1_Y
0 a,b,c 1 0
1 a,b 0 1
2 b,d 1 0
Пока чтотак хорошо.
df['Col1_X'].values.dtype
dtype('uint8')
Получим список всех уникальных подстрок, содержащихся внутри строк, разделенных запятыми, в
Col2
:
vals = list(df['Col2'].str.split(',').values)
vals = [i for l in vals for i in l]
vals = list(set(vals))
vals.sort()
vals
['a', 'b', 'c', 'd']
Теперь мы можем перебрать приведенный выше список значений и использовать
str.contains
для создания нового столбца для каждого значения, например
'a'
.Каждая строка в новом столбце будет содержать 1, если эта строка действительно имеет значение нового столбца, например
'a'
, внутри его строки в
Col2
.Когда мы создаем каждый новый столбец, мы конвертируем его тип данных в
uint8
:
col='Col2'
for v in vals:
n = col + '_' + v
df[n] = df[col].str.contains(v)
df[n] = df[n].astype('uint8')
df.drop(col, axis=1, inplace=True)
df
Col1_X Col1_Y Col2_a Col2_b Col2_c Col2_d
0 1 0 1 1 1 0
1 0 1 1 1 0 0
2 1 0 0 1 0 1
В результате получается кадр данных, который соответствует требуемому формату.И, к счастью, целые числа в четырех новых столбцах, которые были горячо закодированы из Col2
, занимают всего 1 байт каждый, а не 8 байт каждый.
df['Col2_a'].dtype
dtype('uint8')
Если, по внешнему случаю,вышеуказанный подход не работает.Мой совет - использовать str.get_dummies для быстрого кодирования Col2
в кусках строк.Каждый раз, когда вы делаете чанк, вы конвертируете его тип данных из np.int64
в uint8
, а затем преобразует чанк в разреженную матрицу .В конечном итоге вы можете объединить все куски вместе.