Python выборка по условию

Find object in list that has attribute equal to some value (that meets any condition)

I’ve got a list of objects. I want to find one (first or whatever) object in this list that has an attribute (or method result — whatever) equal to value . What’s the best way to find it? Here’s a test case:

class Test: def __init__(self, value): self.value = value import random value = 5 test_list = [Test(random.randint(0,100)) for x in range(1000)] # that I would do in Pascal, I don't believe it's anywhere near 'Pythonic' for x in test_list: if x.value == value: print "i found it!" break 

I think using generators and reduce() won’t make any difference because it still would be iterating through the list. ps.: Equation to value is just an example. Of course, we want to get an element that meets any condition.

The original post is ridiculously out of date, but the 2nd response matches my one-line version exactly. I’m not convinced it’s better than the basic loop version though.

10 Answers 10

next((x for x in test_list if x.value == value), None) 

This gets the first item from the list that matches the condition, and returns None if no item matches. It’s my preferred single-expression form.

for x in test_list: if x.value == value: print("i found it!") break 

The naive loop-break version, is perfectly Pythonic — it’s concise, clear, and efficient. To make it match the behavior of the one-liner:

for x in test_list: if x.value == value: print("i found it!") break else: x = None 

This will assign None to x if you don’t break out of the loop.

great solution, but how do i modify your line so that I can make x.value actually mean x.fieldMemberName where that name is stored in value? field = «name» next((x for x in test_list if x.field == value), None) so that in this case, i am actually checking against x.name, not x.field

Читайте также:  Https sbi sberbank ru 9443 ic dcb print loading html

@StewartDale It’s not totally clear what you’re asking, but I think you mean . if getattr(x, x.fieldMemberName) == value . That will fetch the attribute from x with the name stored in fieldMemberName , and compare it to value .

Since it has not been mentioned just for completion. The good ol’ filter to filter your to be filtered elements.

Functional programming ftw.

####### Set Up ####### class X: def __init__(self, val): self.val = val elem = 5 my_unfiltered_list = [X(1), X(2), X(3), X(4), X(5), X(5), X(6)] ####### Set Up ####### ### Filter one liner ### filter(lambda x: condition(x), some_list) my_filter_iter = filter(lambda x: x.val == elem, my_unfiltered_list) ### Returns a flippin' iterator at least in Python 3.5 and that's what I'm on print(next(my_filter_iter).val) print(next(my_filter_iter).val) print(next(my_filter_iter).val) ### [1, 2, 3, 4, 5, 5, 6] Will Return: ### # 5 # 5 # Traceback (most recent call last): # File "C:\Users\mousavin\workspace\Scripts\test.py", line 22, in # print(next(my_filter_iter).value) # StopIteration # You can do that None stuff or whatever at this point, if you don't like exceptions. 

I know that generally in python list comprehensions are preferred or at least that is what I read, but I don’t see the issue to be honest. Of course Python is not an FP language, but Map / Reduce / Filter are perfectly readable and are the most standard of standard use cases in functional programming.

So there you go. Know thy functional programming.

It won’t get any easier than this:

next(filter(lambda x: x.val == value, my_unfiltered_list)) # Optionally: next(. None) or some other default value to prevent Exceptions 

Источник

Получение выборки из таблицы по нескольким условиям pandas/numpy

Есть таблица в формате csv, из неё нужно получить количество значений удовлетворяющих условию: в столбце TARGET равные нулю и в столбце значения MIP > 82, но меньше 84. Такое выражение не работает:

report[report.TARGET == 0] & report[report.MIP >= 82] & report[report.MIP  

3 ответа 3

Лично я предпочитаю использовать "SQL-подобный" DataFrame.query(), потому, что код получается коротким и легкочитаемым:

res = report.query("""TARGET == 0 and 82  

Вам нужна функция np.logical_and . Эта функция принимает строго два аргумента, поэтому есть два варианта для конъюнкции трёх выражений:

вариант 1: report[np.logical_and(report.TARGET == 0, np.logical_and(report.MIP >= 82,report.MIP

вариант 2: report[np.logical_and.reduce((report.TARGET == 0, report.MIP >= 82,report.MIP

Вот так вообще-то тоже должно работать:

report[(report.TARGET == 0) & (report.MIP >= 82) & (report.MIP  

Обратите внимание на круглые скобки, они обязательны, иначе Pandas выдаёт ошибку, которая начинающим пандоводам непонятна.

Похожие

Подписаться на ленту

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

Дизайн сайта / логотип © 2023 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2023.7.27.43548

Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.

Источник

Выбор значений по условию

И возможно ли получить на выходе данные примерно такого вида (т.е. выбрать строки по условию из первого столбца, и в зависимости от значения третьего столбца (A или B) просуммировать значения 2-го столбца):

array([[650, 2, 'B'], [650, 2, 'A']], d_type=obgect) array([[630, 2, 'A']], d_type=obgect) 

Массив отсортирован по первому значению или вразнобой? Если вразнобой, то скорее всего только перебором всего массива. А если отсортирован, то хотя бы методом половинного деления.

2 ответа 2

import numpy as np a = np.array([[720, 4, 'A'], [710, 1, 'A'], [710, 2, 'B'], [700, 19, 'B'], [670, 1, 'B'], [700, 1, 'A'], [650, 1, 'B'], [650, 1, 'B'], [650, 1, 'A'], [650, 1, 'A'], [640, 1, 'A'], [630, 1, 'A'], [630, 1, 'A'], [610, 5, 'B'], [610, 1, 'B']]) 

Преобразуем объектный тип в целочисленный:

[['650' '1' 'B'] ['650' '1' 'B'] ['650' '1' 'A'] ['650' '1' 'A'] ['630' '1' 'A'] ['630' '1' 'A']] 

Что касается второй части вопроса, то она мне не очень ясна.

Если у вас разные типы данных в различных столбцах, то есть смысл использовать Pandas DataFrame вместо Numpy Array. DataFrame умеет работать со столбцами различных типов данныхю

In [5]: df = pd.DataFrame(data, columns=["col1", "col2", "col3"]) In [6]: df Out[6]: col1 col2 col3 0 720 4 A 1 710 1 A 2 710 2 B 3 700 19 B 4 670 1 B 5 700 1 A 6 650 1 B 7 650 1 B 8 650 1 A 9 650 1 A 10 640 1 A 11 630 1 A 12 630 1 A 13 610 5 B 14 610 1 B In [7]: df.query("col1 in [650, 630]") Out[7]: col1 col2 col3 6 650 1 B 7 650 1 B 8 650 1 A 9 650 1 A 11 630 1 A 12 630 1 A 
In [10]: df.query("col1 in [650, 630]").to_numpy() Out[10]: array([[650, 1, 'B'], [650, 1, 'B'], [650, 1, 'A'], [650, 1, 'A'], [630, 1, 'A'], [630, 1, 'A']], dtype=object) 

Источник

Как отобрать группы строк по условию?

введите сюда описание изображения

Нужно оставить те записи групп id (то есть группируем по id и потом проверяем условие), в которых после строки со значением россия в колонке страна следует строка со значением страны отличным от значения россия и не NaN . Как это можно сделать? Пытаюсь это сделать так:

def pairs(ls): res = [] for i in range(len(ls)-1): res.append([b[i],b[i+1]]) return res def orr(b,k): z = True for i in b: bulev = i == k z = z or bulev return z df = dates.copy() patterns = ["россия", "россия"] res = df.groupby("id").filter(lambda x: orr(pairs(x["страна"].tolist()),patterns)) 

И как должен выглядеть результат если во входных данных будет, например, сначала Украина, а потом Россия ? Т.е. если «россия» будет второй и последней строкой, а другая страна первой.

@MaxU такая группа не должна быть в результате. Важно что после строки со значением россия следует строка со значением отличным от россия (не считая NAN)

2 ответа 2

res = (df .groupby("id") .filter( lambda x: x.iloc[x["страна"].eq("россия").argmax() + 1:, df.columns.get_loc("страна")] .fillna("россия") .ne("россия") .any())) 
In [97]: res Out[97]: фрукт страна id месяц 0 груша франция 01 январь 1 огурец россия 01 март 2 вишня сша 01 январь 3 абрикос россия 02 март 4 груша франция 02 сентябрь 5 арбуз россия 03 март 6 груша сша 03 март 7 банан россия 011 март 8 груша гана 011 ноябрь 9 вишня россия 011 январь 10 яблоко россия 011 январь 11 груша россия 6 март 12 вишня албания 6 январь 
  1. сначала находим порядковый индекс первого вхождения "россия" в группе - x["страна"].eq("россия").argmax()
  2. выбираем все значения в столбце "страна" в группе начиная с найденного в предыдущем шаге индекса + 1. Т.е. выбираем строки начиная со следующей после первого вхождения "россия" в группе - x.loc[x["страна"].eq("россия").argmax() + 1:, df.columns.get_loc("страна")]
  3. меняем NaN -> "россия" : .fillna("россия")
  4. проверяем есть ли в выбранных в предыдущих шагах значениях хотя бы одно значение отличное от "россия" - .ne("россия").any()

В том случае если значения индекса - монотонно возрастающая последовательность можно воспользоваться .loc[] и Series.idxmax() :

res = (df .groupby("id") .filter( lambda x: x.loc[x["страна"].eq("россия").idxmax() + 1:, "страна"] .fillna("россия") .ne("россия") .any())) 

Источник

Оцените статью