Python: нераспределяет много булевых столбцов Pandas DataFrame в один столбец? [dубликат]

У меня была та же проблема, и я нашел решение здесь

Open Terminal и использовал следующий:

gedit $HOME/.pulse/daemon.conf

и поместил следующую строку в файл:

default-sample-rate = 16000

сохранить его, а затем перезапустить pulseaudio в качестве пользователя со следующей командой

pulseaudio --kill && pulseaudio --start

Сделать это для каждого пользователя. [ ! d7]

16
задан 11 July 2018 в 04:50

3 ответа

Прошло несколько лет, так что это, возможно, не было в инструментах pandas, когда этот вопрос изначально был задан, но этот подход мне немного легче. idxmax вернет индекс, соответствующий самому большому элементу (т. е. тот, у кого есть 1). Мы делаем axis=1, потому что хотим имя столбца, где встречается 1.

EDIT: я не стал делать его категоричным, а не просто строкой, но вы можете сделать это так же, как и @Jeff сделал, обернув его pd.Categorical (и pd.Series, если это необходимо).

In [1]: import pandas as pd

In [2]: s = pd.Series(['a', 'b', 'a', 'c'])

In [3]: s
Out[3]: 
0    a
1    b
2    a
3    c
dtype: object

In [4]: dummies = pd.get_dummies(s)

In [5]: dummies
Out[5]: 
   a  b  c
0  1  0  0
1  0  1  0
2  1  0  0
3  0  0  1

In [6]: s2 = dummies.idxmax(axis=1)

In [7]: s2
Out[7]: 
0    a
1    b
2    a
3    c
dtype: object

In [8]: (s2 == s).all()
Out[8]: True

EDIT в ответ на комментарий @ piRSquared: это решение действительно предполагает, что есть один 1 за строку , Я думаю, что это обычно формат. pd.get_dummies может возвращать строки, все 0, если у вас есть drop_first=True или имеются NaN значения и dummy_na=False (по умолчанию) (в любом случае я не хватает?). Строка всех нулей будет обрабатываться так, как если бы это был экземпляр переменной, названной в первом столбце (например, a в примере выше).

Если drop_first=True, у вас нет способа знать только из данных только для манекенов, что такое имя «первой» переменной, так что операция не является обратимой, если вы не храните дополнительную информацию; Я рекомендую оставить drop_first=False (по умолчанию).

Так как dummy_na=False по умолчанию, это может вызвать проблемы. Установите dummy_na=True, когда вы вызываете pd.get_dummies, если хотите использовать это решение для инвертирования «думмификации», а ваши данные содержат любые NaNs. Параметр dummy_na=True всегда будет добавлять столбец «nan», даже если этот столбец равен всем 0, поэтому вы, вероятно, не хотите устанавливать это, если у вас на самом деле нет NaN s. Хорошим подходом может быть установка dummies = pd.get_dummies(series, dummy_na=series.isnull().any()). Хорошо также, что решение idxmax будет правильно восстанавливать ваши NaN s (а не только строку, которая говорит «nan»).

Также стоит упомянуть, что настройка drop_first=True и dummy_na=False означает что NaN s неотличимы от экземпляра первой переменной, поэтому это должно быть сильно обескуражено, если ваш набор данных может содержать любые значения NaN.

20
ответ дан 15 August 2018 в 15:50
  • 1
    Это не выполняется, когда строка - это все нули. Он работает для этого примера и в предположении, что существует одно и только одно значение 1 для каждой строки. – piRSquared 14 August 2018 в 16:29

Настройка

Использование настройки @ Jeff

s = Series(list('aaabbbccddefgh')).astype('category')
df = pd.get_dummies(s)

Если столбцы являются строками

, и существует только один 1 на строку

df.dot(df.columns)

0     a
1     a
2     a
3     b
4     b
5     b
6     c
7     c
8     d
9     d
10    e
11    f
12    g
13    h
dtype: object

numpy.where

Снова! Предполагая, что в строке

i, j = np.where(df)
pd.Series(df.columns[j], i)

0     a
1     a
2     a
3     b
4     b
5     b
6     c
7     c
8     d
9     d
10    e
11    f
12    g
13    h
dtype: category
Categories (8, object): [a, b, c, d, e, f, g, h]

numpy.where

не допущено ни одного 1 Не предполагается 1 за строку

i, j = np.where(df)
pd.Series(dict(zip(zip(i, j), df.columns[j])))

0   0    a
1   0    a
2   0    a
3   1    b
4   1    b
5   1    b
6   2    c
7   2    c
8   3    d
9   3    d
10  4    e
11  5    f
12  6    g
13  7    h
dtype: object

numpy.where

Если мы не принимаем одну 1 за строку и отбрасываем индекс

i, j = np.where(df)
pd.Series(dict(zip(zip(i, j), df.columns[j]))).reset_index(-1, drop=True)

0     a
1     a
2     a
3     b
4     b
5     b
6     c
7     c
8     d
9     d
10    e
11    f
12    g
13    h
dtype: object
0
ответ дан 15 August 2018 в 15:50

Это довольно поздний ответ, но, поскольку вы просите быстрый способ сделать это, я предполагаю, что вы ищете самую эффективную стратегию. На большом фрейме данных (например, 10000 строк) вы можете получить очень значительное повышение скорости с помощью np.where вместо idxmax или get_level_values и получить тот же результат. Идея состоит в том, чтобы индексировать имена столбцов, где фиктивный фреймворк не равен 0:

Метод:

Использование тех же данных образца, что и @Nathan:

>>> dummies
   a  b  c
0  1  0  0
1  0  1  0
2  1  0  0
3  0  0  1

s2 = pd.Series(dummies.columns[np.where(dummies!=0)[1]])

>>> s2
0    a
1    b
2    a
3    c
dtype: object

Бенчмарк:

На небольшом фиктивном фрейме вы не увидите большой разницы в производительности. Тем не менее, тестирование различных стратегий решения этой проблемы на большой серии:

s = pd.Series(np.random.choice(['a','b','c'], 10000))

dummies = pd.get_dummies(s)

def np_method(dummies=dummies):
    return pd.Series(dummies.columns[np.where(dummies!=0)[1]])

def idx_max_method(dummies=dummies):
    return dummies.idxmax(axis=1)

def get_level_values_method(dummies=dummies):
    x = dummies.stack()
    return pd.Series(pd.Categorical(x[x!=0].index.get_level_values(1)))

def dot_method(dummies=dummies):
    return dummies.dot(dummies.columns)

import timeit

# Time each method, 1000 iterations each:

>>> timeit.timeit(np_method, number=1000)
1.0491090340074152

>>> timeit.timeit(idx_max_method, number=1000)
12.119140846014488

>>> timeit.timeit(get_level_values_method, number=1000)
4.109266621991992

>>> timeit.timeit(dot_method, number=1000)
1.6741622970002936

Метод np.where примерно в 4 раза быстрее, чем метод get_level_values в 11,5 раз быстрее, чем метод idxmax! Он также бьет (но немного) метод .dot(), описанный в этом ответе на аналогичный вопрос

. Все они возвращают тот же результат:

>>> (get_level_values_method() == np_method()).all()
True
>>> (idx_max_method() == np_method()).all()
True
3
ответ дан 15 August 2018 в 15:50

Другие вопросы по тегам:

Похожие вопросы: