2 votes

Comment compter le nombre d'occurrences de la valeur d'une colonne dans une colonne de listes ?

Considérez le dataframe suivant:

    column_of_lists   scalar_col
0   [100, 200, 300]       100
1   [100, 200, 200]       200
2   [300, 500]            300
3   [100, 100]            200

La sortie désirée serait une Série, représentant combien de fois la valeur scalaire de scalar_col apparaît à l'intérieur de la colonne de listes.

Donc, dans notre cas:

1 # 100 apparaît une fois dans sa liste respective
2 # 200 apparaît deux fois dans sa liste respective
1 # ...
0

J'ai essayé quelque chose du genre:

df['column_of_lists'].apply(lambda x: x.count(df['scalar_col'])

et je comprends que cela ne fonctionnera pas car je lui demande de compter une Série au lieu d'une valeur unique.

Toute aide serait la bienvenue!

6voto

jezrael Points 290608

Utilisez la compréhension de liste :

df['new'] = [x.count(y) for x,y in zip(df['column_of_lists'], df['scalar_col'])]
print (df)
   column_of_lists  scalar_col  new
0  [100, 200, 300]         100    1
1  [100, 200, 200]         200    2
2       [300, 500]         300    1
3       [100, 100]         200    0

Si la performance n'est pas importante, utilisez DataFrame.apply avec axis=1:

df["new"] = df.apply(lambda x: x["column_of_lists"].count(x["scalar_col"]), axis=1)

#40k rows
df = pd.concat([df] * 10000, ignore_index=True)

In [145]: %timeit df["new1"] = df.apply(lambda x: x["column_of_lists"].count(x["scalar_col"]), axis=1)
572 ms ± 99.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [146]: %timeit df['new2'] = [x.count(y) for x,y in zip(df['column_of_lists'], df['scalar_col'])]
22.7 ms ± 840 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [147]: %%timeit
     ...: x = df.explode('column_of_lists')
     ...: df['counts'] = x.column_of_lists.eq(x.scalar_col).groupby(x.index).sum()
     ...: 
61.2 ms ± 306 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

1voto

The6thSense Points 5743

Vous utilisez count et appliquez.

Code:

import pandas as pd
in_df = pd.DataFrame({"column_of_lists": [[100, 200, 300] , 
                                        [100, 200, 200], 
                                        [300, 500], [100, 100]],
            "scalar_col": [100, 200, 300, 200]})
in_df["Match_Count"] = in_df.apply(lambda x:x["column_of_lists"].count(x["scalar_col"]), axis=1)

Sortie:

column_of_lists  scalar_col  Match_Count
0  [100, 200, 300]         100            1
1  [100, 200, 200]         200            2
2       [300, 500]         300            1
3       [100, 100]         200            0

1voto

Vishnudev Points 1702

Une approche vectorisée pour des listes plus grandes consisterait à utiliser DataFrame.explode puis GroupBy.sum

x = df.explode('column_of_lists')
df['counts'] = x.column_of_lists.eq(x.scalar_col).groupby(x.index).sum()

Sortie

   column_of_lists  scalar_col  counts
0  [100, 200, 300]         100       1
1  [100, 200, 200]         200       2
2       [300, 500]         300       1
3       [100, 100]         200       0

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X