Skip to content Skip to sidebar Skip to footer

Count And Remove Elements By Conditions From Dataframe Columns Of Lists

Suppose I have a Pandas df col_name 1 [16, 4, 30] 2 [5, 1, 2] 3 [4, 5, 52, 888] 4 [1, 2, 4] 5 [5, 99, 4, 75, 1, 2] I would like to remove all the elemen

Solution 1:

Option 1 Somewhat plain vanilla approach

s = pd.Series({(i, j): x for (i, r) in df.col_name.items() for j, x inenumerate(r)})

f, u = pd.factorize(s.values)

s[(np.bincount(f) >= 3)[f]].groupby(level=0).apply(list).to_frame('col_name')

       col_name
0           [4]
1     [5, 1, 2]
2        [4, 5]
3     [1, 2, 4]
4  [5, 4, 1, 2]

Option 2 Over the top complicated approach

lens = df.col_name.str.len().values
splits = lens.cumsum()[:-1]
values = np.concatenate(df.col_name.values)
f, u = pd.factorize(values)
b = np.bincount(f)
r = np.arange(len(df)).repeat(lens)
m = (b >= 3)[f]
new_splits = splits - np.bincount(r, ~m).astype(int).cumsum()[:-1]
new_values = np.split(values[m], new_splits)
df.assign(col_name=new_values)

       col_name
0           [4]
1     [5, 1, 2]
2        [4, 5]
3     [1, 2, 4]
4  [5, 4, 1, 2]

Solution 2:

You can get all values less as treshold by value_counts with boolean indexing:

from  itertools import chain

a = pd.Series(list(chain.from_iterable(df['col_name']))).value_counts()
a = a.index[a >= 3]
print (a)
Int64Index([4, 5, 2, 1], dtype='int64')

df = df.applymap(lambda x: [v for v in x if v in a])
print (df)
       col_name
1           [4]
2     [5, 1, 2]
3        [4, 5]
4     [1, 2, 4]
5  [5, 4, 1, 2]

Solution 3:

First get counts and then apply or applymap your conditional check for elements.

In [2707]:counts=pd.Series([vforxindf.col_nameforvinx]).value_counts()In [2708]:df.col_name.apply(lambdax: [vforvinxifcounts[v] >=3])Out[2708]:1             [4]
2       [5, 1, 2]
3          [4, 5]
4       [1, 2, 4]
5    [5, 4, 1, 2]
Name:col_name,dtype:objectIn [2709]:df.applymap(lambdax: [vforvinxifcounts[v] >=3])Out[2709]:col_name1           [4]
2     [5, 1, 2]
3        [4, 5]
4     [1, 2, 4]
5  [5, 4, 1, 2]

Details

In[2710]: countsOut[2710]:
445323133018881521161751991dtype: int64

Solution 4:

You can use Counter() from collections:

import pandas as pd
from collections import Counter

limit = 3

df = pd.DataFrame({'col_name': [[16, 4, 30], [5, 1, 2], [4, 5, 52, 888], [1, 2, 4], [5, 99, 4, 75, 1, 2]]})

flat = Counter([y for x in df.col_name for y in x])
desired = [k for k, v in flat.items() if v >= limit]

df['col_name'] = df['col_name'].apply(lambda x: [i for i in x if i in desired])

Solution 5:

Similar to this, using collections.Counter (but developed independently, with a few optimisations);

from collections import Counter
c = Counter(pd.Series(np.concatenate(df.col_name.tolist())))

deffoo(array):
    return [x  for x in array if c[x] >= 3]

df.col_name = df.col_name.apply(foo)
df

       col_name
1           [4]
2     [5, 1, 2]
3        [4, 5]
4     [1, 2, 4]
5  [5, 4, 1, 2]

Post a Comment for "Count And Remove Elements By Conditions From Dataframe Columns Of Lists"