Disons que j'ai l'exemple suivant
items = ['milk', 'bread', 'water'] df: name item1 item2 item3 items_1 milk water items_2 milk rubber juice items_3 juice paper wood items_4 bread items_5 bread water milk items_6 milk juice
Dans cet exemple, je voudrais obtenir toutes les lignes df dont les membres sont complètement dans la liste des éléments, ce qui signifie:
Maintenant, le vrai dataframe "df" contiendra plusieurs millions de lignes, c'est-à-dire items_ *, d'où le "efficacement" dans le titre. Le nombre de colonnes de "df" sera compris entre 10 et 20. De plus, il y aura plusieurs milliers de listes "items" avec entre 10 et 20 éléments.
Quelqu'un peut-il m'aider s'il vous plaît sur celui-ci ?
4 Réponses :
for item in dflist: if item not in items: print("this df list has an items that is not in the items list") I know that the output isn't probably what you are looking to have as an output but your ideal output is unclear. What this for loop does is it will cycle through each item in your df lists (ex. items_1, items_2, etc.). It will look at each item in this list and will check if it is in the list of items you are checking against. If it finds an item that is not in the list of items you are checking against it will return that it has found an item not in your checking list. This seems what you are looking for, any value that is not in the first list of items labeled "items". So this checks for those and from here you could easily discard those.Generally when searching a big data set, binary search is the way to go, however this does not seem that feasible in this situation unless you can put the df lists in alphabetical order, if you cannot I would do what I wrote above.Hope this makes sense!
Nous devons trouver un moyen d'affirmer que les lignes sont complètement dans la liste items
, tout en considérant les entrées nulles. Une combinaison de isin , sum et notna peut vous aider:
#set name as index #allows us to focus on the items columns #and later allows easy filtering df = df.set_index("name") #find rows that are in items #and get the sum of the boolean A = df.isin(items).sum(1) #get the sum of rows #that are not boolean #this helps us narrow down #items completely in the items list #that are yet affected by null entries B = df.notna().sum(1) #compare A and B #if they match, that implies complete entry in items list cond = A.eq(B) #let's see what cond looks : cond name items_1 True items_2 False items_3 False items_4 True items_5 True items_6 False dtype: bool #filter df with condition to get your rows df.loc[cond] item1 item2 item3 name items_1 milk water None items_4 bread None None items_5 bread water milk
Une autre solution:
Si votre dataframe ressemble à:
item1 item2 item3 name items_1 milk water items_4 bread items_5 bread water milk
items = pd.Series(items + ['']) m = df.apply(lambda x: x.isin(items).all(), axis=1) print(df[m])
Vous pouvez faire:
XXX
Impressions:
item1 item2 item3 name items_1 milk water items_2 milk rubber juice items_3 juice paper wood items_4 bread items_5 bread water milk items_6 milk juice
Utilisez ~ isin pour vérifier si la condition n'est PAS Vrai pour toutes les valeurs, récupérez l'index, utilisez l'indexation booléenne. Vous obtenez
true_names = df[~df.iloc[:, 1:].isin(items)].isnull().all(1) df.loc[true_names, 'name'] 0 name_1 3 name_4 4 name_5
Merci d'avoir répondu. J'ai essayé votre proposition et cela a accéléré le temps d'exécution. J'essaierai également les autres réponses pour voir si une solution est encore plus rapide que la vôtre.
Quand vous dites complètement dans la liste, vous voulez dire le lait, le pain, l'eau doivent tous être dans la rangée, n'est-ce pas?
Prenez la ligne items_1, vérifiez si chaque élément de cette ligne est également dans la liste des éléments. dans ce cas, le lait et l'eau sont tous deux dans la liste des articles (lait, pain, eau) et c'est la ligne qui m'intéresse. De plus, tout ce qui se trouve sous la ligne items_4 (juste le pain dans ce cas) est contenu dans la liste des articles. J'espère que cela clarifie un peu le problème.