#python #list #math
#python #Список #математика
Вопрос:
У меня есть переменная, которая выглядит следующим образом: my_value = 188
и у меня есть список, который выглядит следующим образом:
my_list = [
['Morocco', 'Meat', '190,00', '0,15'],
['Morocco', 'Meat', '189,90', '0,32'],
['Morocco', 'Meat', '189,38', '0,44'],
['Morocco', 'Meat', '188,94', '0,60'],
['Morocco', 'Meat', '188,49', '0,78'],
['Morocco', 'Meat', '187,99', '0,101'],
['Spain', 'Meat', '190,76', '0,10'],
['Spain', 'Meat', '190,16', '0,20'],
['Spain', 'Meat', '189,56', '0,35'],
['Spain', 'Meat', '189,01', '0,40'],
['Spain', 'Meat', '188,13', '0,75'],
['Spain', 'Meat', '187,95', '0,85'],
['Italy', 'Meat', '190,20', '0,11'],
['Italy', 'Meat', '190,10', '0,31'],
['Italy', 'Meat', '189,32', '0,45'],
['Italy', 'Meat', '188,61', '0,67'],
['Italy', 'Meat', '188,01', '0,72'],
['Italy', 'Meat', '187,36', '0,80']]
Как вы можете видеть, my_list
числа в индексе [2]
убывают, а числа в индексе [3]
возрастают. Теперь для каждого списка я хочу проверить, по какому индексу [3]
индекс [2]
является самым близким my_value
, НО он не должен опускаться ниже my_value.
Я попробовал приведенный ниже код:
for key,sublists in itertools.groupby(my_list,lambda y:y[0]):
v=[] #initialize it in case no element fulfill the condition
for v in itertools.takewhile(lambda x:float(x[-1].replace(",","."))<my_value ,sublists):
pass
if v:
print(v[-1])
Я получил следующий вывод:
0,101
0,85
0,80
Результат, который я хочу, это:
0,78
0,75
0,72
Комментарии:
1. Что вы подразумеваете под «превзойти ваше значение»? В вашем примере желаемого результата все значения с индексом 2 больше 188 и, следовательно, превышают ваше значение. Вы имеете в виду, что они не должны опускаться ниже вашего значения?
2. @sunnytown с превышением, я имею в виду
<188
. Все наоборот. Я должен изменить свой словарь. Вместо того, чтобы превосходить, я имею в виду «падение ниже». Вы понимаете?3. Да, я просто хотел уточнить, действительно ли это то, что вы имеете в виду.
Ответ №1:
Это та работа, в которой pandas
приходит на помощь:
import pandas as pd
my_value = 188
my_list = [] # complete this with your list above
df = pd.DataFrame(my_list) # make a DataFrame out of your list
df[2] = df[2].str.replace(",", ".").astype(float) # convert those strings to actual floats
df[3] = df[3].str.replace(",", ".").astype(float)
selected = df[df[2]>my_value].groupby(by=0).agg({2:'min',3:'last'}) # selects what you want
print(list(selected[3])) # if you just want those values
выведет
[0.72, 0.78, 0.75]
selected
будет выглядеть так:
0 2 3
Italy 188.01 0.72
Morocco 188.49 0.78
Spain 188.13 0.75
Ответ №2:
my_value = 188
numbers = [float(line[2].replace(',', '.')) for line in my_list]
minima = [(num - my_value, line[3]) for num, line in zip(numbers, my_list) if num >= my_value]
minima = sorted(minima, key=lambda x: x[0])
top3 = [val[1] for val in minima[:3]]
print(top3)
Сначала я создаю список numbers
, который содержит значения индекса 2 каждого списка в my_list
преобразованном виде с плавающей точкой, поэтому мы действительно можем выполнять вычисления с этими числами. Это делается с использованием понимания списка.
Затем я создаю новый список minima
, в котором я вычисляю разницу между my_value
и всеми значениями numbers
, с условием, что значение в числах должно быть больше или равно my_number
. Используя zip(number, my_list)
одновременный цикл как списка numbers
, my_list
так и для того, чтобы я мог объединить разницу num - myvalue
вместе с соответствующим значением в индексе 3 my_list
в кортеж.
Затем список minima
выглядит следующим образом:
[(2.0, '0,15'),
(1.9000000000000057, '0,32'),
(1.3799999999999955, '0,44'),
(0.9399999999999977, '0,60'),
(0.4900000000000091, '0,78'),
(2.759999999999991, '0,10'),
(2.1599999999999966, '0,20'),
(1.5600000000000023, '0,35'),
(1.009999999999991, '0,40'),
(0.12999999999999545, '0,75'),
(2.1999999999999886, '0,11'),
(2.0999999999999943, '0,31'),
(1.3199999999999932, '0,45'),
(0.6100000000000136, '0,67'),
(0.009999999999990905, '0,72')]
Затем я сортирую этот список в порядке возрастания по его первому значению в кортеже, которое является разницей между my_value
и числами в индексе 3. Затем я беру первые три и возвращаю только второе значение в кортеже.
Просто в качестве примечания: если вы имеете дело с табличными данными, подобными этому, было бы неплохо заглянуть в библиотеку pandas. Другой ответ на этот пост показывает способ сделать это с помощью pandas. С помощью этой библиотеки часто бывает проще и удобнее работать с табличными данными, поскольку она предлагает множество функциональных возможностей для простого выполнения большого количества операций с данными и анализа.
Комментарии:
1. Ваш
top3
выдает правильный вывод. Можете ли вы дать подробное объяснение того, что вы на самом деле сделали?2. Я отредактировал свой пост с объяснением.
3. @TangerCity Вы уверены, что это дает правильную перестройку? Кажется, что это только случайно дает правильный результат, потому что значения находятся в одинаковом диапазоне для каждой страны.
4. О, возможно, я действительно неправильно понял вопрос. Вероятно, это правда, что это не всегда даст правильный результат, поскольку я не группирую по странам. Извините за это.
5. @sunnytown Как вы добавляете эту группировку по странам?
Ответ №3:
Почему бы не использовать встроенную функцию сортировки()?:
my_list = [row for row in my_list if float(row[2].replace(',','.')) >= my_value]
my_list.sort(key=lambda l:float(l[2].replace(',','.')))
for row in my_list:
print(row)
>
['Italy', 'Meat', '188,01', '0,72']
['Spain', 'Meat', '188,13', '0,75']
['Morocco', 'Meat', '188,49', '0,78']
['Italy', 'Meat', '188,61', '0,67']
['Morocco', 'Meat', '188,94', '0,60']
['Spain', 'Meat', '189,01', '0,40']
['Italy', 'Meat', '189,32', '0,45']
['Morocco', 'Meat', '189,38', '0,44']
['Spain', 'Meat', '189,56', '0,35']
['Morocco', 'Meat', '189,90', '0,32']
['Morocco', 'Meat', '190,00', '0,15']
['Italy', 'Meat', '190,10', '0,31']
['Spain', 'Meat', '190,16', '0,20']
['Italy', 'Meat', '190,20', '0,11']
['Spain', 'Meat', '190,76', '0,10']