.*
Если пользователь хочет дать вам свой номер телефона, то доверьтесь ему, чтобы все было правильно. Если он не хочет отдать его вам, то заставляя его ввести действительный номер, он отправит его на сайт конкурента или заставит его ввести случайную строку, соответствующую вашему регулярному выражению. Возможно, у меня даже возникнет соблазн найти номер сексуальной линии премиум-класса и введите это вместо.
Я также рассмотрел бы любое из следующих утверждений на веб-сайте:
"123 456 7890 until 6pm, then 098 765 4321"
"123 456 7890 or try my mobile on 098 765 4321"
"ex-directory - mind your own business"
Использование s
для вашего df['groups']
:
In [21]: s = pd.Series({0: ['a', 'b', 'c'], 1:['c'], 2: ['b', 'c', 'e'], 3: ['a', 'c'], 4: ['b', 'e'] })
In [22]: s
Out[22]:
0 [a, b, c]
1 [c]
2 [b, c, e]
3 [a, c]
4 [b, e]
dtype: object
Это возможное решение:
In [23]: pd.get_dummies(s.apply(pd.Series).stack()).sum(level=0)
Out[23]:
a b c e
0 1 1 1 0
1 0 0 1 0
2 0 1 1 1
3 1 0 1 0
4 0 1 0 1
Логика этого:
.apply(Series)
преобразует серию списков в dataframe .stack()
снова помещает все в один столбец (создавая многоуровневый индекс) pd.get_dummies( )
создавая манекены .sum(level=0
) для объединения разных строк, которые должны быть одной строкой (путем суммирования второго уровня, сохраняя только исходный уровень (level=0
)) Небольшой эквивалент pd.get_dummies(s.apply(pd.Series), prefix='', prefix_sep='').sum(level=0, axis=1)
Если это будет достаточно эффективно, я не знаю, но в любом случае, если производительность важна, сохранение списков в фрейме данных не очень хорошая идея.
Несмотря на то, что на этот квест был дан ответ, у меня есть более быстрое решение:
df.groups.apply(lambda x: pd.Series([1] * len(x), index=x)).fillna(0, downcast='infer')
И если у вас есть пустые группы или NaN
, вы можете просто:
df.loc[df.groups.str.len() > 0].apply(lambda x: pd.Series([1] * len(x), index=x)).fillna(0, downcast='infer')
Внутри лямбда x
- ваш список, например ['a', 'b', 'c']
. Таким образом, pd.Series
будет выглядеть следующим образом:
In [2]: pd.Series([1, 1, 1], index=['a', 'b', 'c'])
Out[2]:
a 1
b 1
c 1
dtype: int64
Когда все pd.Series
объединяются, они становятся pd.DataFrame
, а их index
становятся columns
; missing index
стал column
с NaN
, как вы можете видеть дальше:
In [4]: a = pd.Series([1, 1, 1], index=['a', 'b', 'c'])
In [5]: b = pd.Series([1, 1, 1], index=['a', 'b', 'd'])
In [6]: pd.DataFrame([a, b])
Out[6]:
a b c d
0 1.0 1.0 1.0 NaN
1 1.0 1.0 NaN 1.0
Теперь fillna
заполняет те NaN
с помощью 0
:
In [7]: pd.DataFrame([a, b]).fillna(0)
Out[7]:
a b c d
0 1.0 1.0 1.0 0.0
1 1.0 1.0 0.0 1.0
И downcast='infer'
должен опуститься от float
до int
:
In [11]: pd.DataFrame([a, b]).fillna(0, downcast='infer')
Out[11]:
a b c d
0 1 1 1 0
1 1 1 0 1
PS .: Не требуется использование .fillna(0, downcast='infer')
.
dummies.columns = ['D_'+col_name for col_name in dummies.columns]
– Ufos
13 November 2017 в 00:06
Очень быстрое решение, если у вас большой размер данных
Использование sklearn.preprocessing.MultiLabelBinarizer
import pandas as pd
from sklearn.preprocessing import MultiLabelBinarizer
df = pd.DataFrame(
{'groups':
[['a','b','c'],
['c'],
['b','c','e'],
['a','c'],
['b','e']]
}, columns=['groups'])
s = df['groups']
mlb = MultiLabelBinarizer()
pd.DataFrame(mlb.fit_transform(s),columns=mlb.classes_, index=df.index)
Результат:
a b c e
0 1 1 1 0
1 0 0 1 0
2 0 1 1 1
3 1 0 1 0
4 0 1 0 1
pd.get_dummies(s.apply(pd.Series), prefix='', prefix_sep='').sum(level=0, axis=1)
, поскольку ваш код выводит серию с суммой, а не фреймворком данных. – Primer 13 March 2015 в 16:49get_dummies
в приложении (так что для каждой строки, а не один раз на всех), что сделало ее медленнее, как подход выше. – joris 13 March 2015 в 17:15