У меня в столбце данных pandas есть столбец, который содержит большое количество списков меток:

>>> data['SPLIT'].head(10)
0    [33.23, 88.72, 38.93, E931.7, V09.0, 041.11, 5...
1    [99.04, 38.06, 39.57, 00.91, 55.69, V15.82, 27...
2    [96.04, 96.72, 401.9, 276.5, 584.9, 428.0, 507...
3    [96.6, 99.15, 99.83, V29.0, 765.15, 765.25, 77...
4    [96.71, 96.04, 54.12, 99.60, 38.93, 99.15, 53....
5    [88.72, 37.61, 39.61, 36.15, 36.12, 272.0, 401...
6    [38.93, 88.72, 37.31, 272.4, 719.46, 722.0, 31...
7    [88.72, 39.61, 35.71, 272.4, V12.59, 458.29, 7...
8    [97.44, 99.04, 88.56, 37.23, 39.95, 38.95, 00....
9    [00.14, 89.61, 39.95, E878.8, 244.9, 443.9, 18...

Я пытаюсь перебрать все эти списки, чтобы найти общее вхождение каждого значения, чтобы я мог найти 50 наиболее часто встречающихся значений.

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

test = pd.Series(sum([item for item in data.SPLIT], [])).value_counts()

Я попытался написать функцию снаружи, чтобы пройтись по спискам и найти счетчик, но это также было очень медленно.

Можно ли как-то изменить эти данные или использовать функцию в пандах, которая имеет производительность, аналогичную df.groupby.count()?

Я полчаса искал в google и stackoverflow, но ни один из ответов не показал лучшую производительность. Я долго пытался найти способ сгладить список или найти способ отобразить счетчики с лучшей скоростью (итерации по 500 тыс. Строк и длина каждого списка различна, некоторые могут достигать 512, другие короткие как 2).

3
Ben C Wang 14 Апр 2019 в 10:21

2 ответа

Лучший ответ

Вместо этого используйте понимание списка с выравниванием sum:

test = pd.Series([x for item in data.SPLIT for x in item]).value_counts()

Или с помощью chain.from_iterable:

from itertools import chain

test = pd.Series(list(chain.from_iterable(data.SPLIT))).value_counts()

Или используйте также collections.Counter:

from itertools import chain
from collections import Counter

test = pd.Series(Counter(chain.from_iterable(data.SPLIT)))

Или же:

import functools, operator

test = pd.Series(functools.reduce(operator.iconcat, data.SPLIT, [])).value_counts()

Чистый раствор панд:

test = pd.DataFrame(data.SPLIT.values.tolist()).stack().value_counts()
2
jezrael 14 Апр 2019 в 08:34

Как насчет этого?

import pandas as pd

split = data["SPLIT"].apply(pd.Series)
split = split.rename(columns = lambda x : 'val_' + str(x))
split.melt(value_name="val").groupby(["val"]).size()
1
pythonjokeun 14 Апр 2019 в 07:50