У меня есть dataframe, где в одном столбце у меня есть список значений хеш-функции, хранящихся как строки:

'[d85235f50b3c019ad7c6291e3ca58093,03e0fb034f2cb3264234b9eae09b4287]' just to be clear.

Датафрейм выглядит так

  1
0 [8a88e629c368001c18619c7cd66d3e96, 4b0709dd990a0904bbe6afec636c4213, c00a98ceb6fc7006d572486787e551cc, 0e72ae6851c40799ec14a41496d64406, 76475992f4207ee2b209a4867b42c372]
1 [3277ded8d1f105c84ad5e093f6e7795d]
2 [d85235f50b3c019ad7c6291e3ca58093, 03e0fb034f2cb3264234b9eae09b4287]

Я хотел бы создать список уникальных хеш-идентификаторов, присутствующих в этом столбце.

Какой эффективный способ? Спасибо

3
user3620915 29 Авг 2017 в 18:00

3 ответа

Лучший ответ

Вариант 1
Смотрите сроки ниже для быстрого выбора

Вы можете встроить разбор и выравнивание в одно понимание

[y for x in df['1'].values.tolist() for y in x.strip('[]').split(', ')]

['8a88e629c368001c18619c7cd66d3e96',
 '4b0709dd990a0904bbe6afec636c4213',
 'c00a98ceb6fc7006d572486787e551cc',
 '0e72ae6851c40799ec14a41496d64406',
 '76475992f4207ee2b209a4867b42c372',
 '3277ded8d1f105c84ad5e093f6e7795d',
 'd85235f50b3c019ad7c6291e3ca58093',
 '03e0fb034f2cb3264234b9eae09b4287']

Оттуда вы можете использовать list(set()), pd.unique или np.unique

pd.unique([y for x in df['1'].values.tolist() for y in x.strip('[]').split(', ')])

array(['8a88e629c368001c18619c7cd66d3e96',
       '4b0709dd990a0904bbe6afec636c4213',
       'c00a98ceb6fc7006d572486787e551cc',
       '0e72ae6851c40799ec14a41496d64406',
       '76475992f4207ee2b209a4867b42c372',
       '3277ded8d1f105c84ad5e093f6e7795d',
       'd85235f50b3c019ad7c6291e3ca58093',
       '03e0fb034f2cb3264234b9eae09b4287'], dtype=object)

Вариант 2
Для краткости используйте pd.Series.extractall

list(set(df['1'].str.extractall('(\w+)')[0]))

['8a88e629c368001c18619c7cd66d3e96',
 '4b0709dd990a0904bbe6afec636c4213',
 'c00a98ceb6fc7006d572486787e551cc',
 '0e72ae6851c40799ec14a41496d64406',
 '76475992f4207ee2b209a4867b42c372',
 '3277ded8d1f105c84ad5e093f6e7795d',
 'd85235f50b3c019ad7c6291e3ca58093',
 '03e0fb034f2cb3264234b9eae09b4287']

@ jezrael list(set()) с моим пониманием быстрее всего

Время разбора
Я сохранил то же самое list(set()) для сравнения парсинга и сплющивания.

%timeit list(set(np.concatenate(df['1'].apply(yaml.load).values).tolist()))
%timeit list(set([y for x in df['1'].values.tolist() for y in x.strip('[]').split(', ')]))
%timeit list(set(chain.from_iterable(df['1'].str.strip('[]').str.split(', '))))
%timeit list(set(df['1'].str.extractall('(\w+)')[0]))

1.01 ms ± 45 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
6.42 µs ± 219 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
279 µs ± 8.87 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
941 µs ± 10.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Это берет мое понимание и использует различные способы сделать уникальными, чтобы сравнить эти скорости

%timeit pd.unique([y for x in df['1'].values.tolist() for y in x.strip('[]').split(', ')])
%timeit np.unique([y for x in df['1'].values.tolist() for y in x.strip('[]').split(', ')])
%timeit list(set([y for x in df['1'].values.tolist() for y in x.strip('[]').split(', ')]))

57.8 µs ± 3.66 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
17.5 µs ± 552 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
6.18 µs ± 184 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
5
piRSquared 29 Авг 2017 в 16:53

Вам нужен strip с split сначала и для разжигания chain:

print (df.columns.tolist())
['col']

#convert strings to lists per rows
#change by your column name if necessary    
s = df['col'].str.strip('[]').str.split(', ')
print (s)
0    [8a88e629c368001c18619c7cd66d3e96, 4b0709dd990...
1                   [3277ded8d1f105c84ad5e093f6e7795d]
2    [d85235f50b3c019ad7c6291e3ca58093, 03e0fb034f2...
Name: col, dtype: object

#check first value
print (type(s.iat[0]))
<class 'list'>

#get unique values - for unique values use set
from  itertools import chain
L = list(set(chain.from_iterable(s)))

['76475992f4207ee2b209a4867b42c372', '3277ded8d1f105c84ad5e093f6e7795d',
 'd85235f50b3c019ad7c6291e3ca58093', '4b0709dd990a0904bbe6afec636c4213', 
 'c00a98ceb6fc7006d572486787e551cc', '03e0fb034f2cb3264234b9eae09b4287', 
 '8a88e629c368001c18619c7cd66d3e96', '0e72ae6851c40799ec14a41496d64406']

from  itertools import chain
s = [x.strip('[]').split(', ') for x in df['col'].values.tolist()]
L = list(set(chain.from_iterable(s)))
print (L)

['76475992f4207ee2b209a4867b42c372', '3277ded8d1f105c84ad5e093f6e7795d', 
 'd85235f50b3c019ad7c6291e3ca58093', '4b0709dd990a0904bbe6afec636c4213', 
 'c00a98ceb6fc7006d572486787e551cc', '03e0fb034f2cb3264234b9eae09b4287',
 '8a88e629c368001c18619c7cd66d3e96', '0e72ae6851c40799ec14a41496d64406']
3
jezrael 29 Авг 2017 в 16:44

IIUC, вы хотите сгладить ваши данные. Преобразуйте его в столбец списков, используя yaml.load.

import yaml

df = df.applymap(yaml.load)
print(df)
                                            1
0  [8a88e629c368001c18619c7cd66d3e96, 4b0709dd990...
1                 [3277ded8d1f105c84ad5e093f6e7795d]
2  [d85235f50b3c019ad7c6291e3ca58093, 03e0fb034f2...

Самый простой способ - создать новый фрейм данных из значений старого.

out = pd.DataFrame(np.concatenate(df.iloc[:, 0].values.tolist()))
print(out)

                                  0
0  8a88e629c368001c18619c7cd66d3e96
1  4b0709dd990a0904bbe6afec636c4213
2  c00a98ceb6fc7006d572486787e551cc
3  0e72ae6851c40799ec14a41496d64406
4  76475992f4207ee2b209a4867b42c372
5  3277ded8d1f105c84ad5e093f6e7795d
6  d85235f50b3c019ad7c6291e3ca58093
7  03e0fb034f2cb3264234b9eae09b4287
2
cs95 29 Авг 2017 в 16:09