#python-3.x #dataframe #pandas-groupby #data-filtering
#python-3.x #фрейм данных #pandas-groupby #фильтрация данных
Вопрос:
У меня есть фрейм данных как со строковыми, так и с целочисленными значениями.
Прикрепление образца словаря данных для понимания фрейма данных, который у меня есть:
data = {
'col1': ['A','A','A','B','B','B','C','C','C','D','D','D'],
'col2': [10,20,30,10,20,30,10,20,30,10,20,30],
'col3': ['X','X','X','X','Y','X','X','X','Y','Y','X','X'],
'col4': [45,23,78,56,12,34,87,54,43,89,43,12]
'col5': [3,4,6,4,3,2,4,3,5,3,4,6]
}
Мне нужно извлечь данные, как указано ниже:
- Максимальное значение из col4
- Сгруппировано по col1
- Отфильтровывается col3 из результата, если значение равно Y
- Отфильтруйте col5 из результата, чтобы отображать только значения не более 5.
Итак, я попробовал кое-что и столкнулся со следующими проблемами.
1- Я использовал следующий метод, чтобы найти максимальное значение из данных. Но я не могу найти максимальное значение для каждой группы.
print(dataframe['col4'].max()) #this worked to get one max value
print(dataframe.groupby('col1').max() #this doesn't work
Второй вариант не работает для меня, поскольку он также возвращает максимальное значение для col2. Мне нужно, чтобы результат имел значение col2 против максимальной строки в каждой группе.
2- Я не могу применить фильтр как к col3 (str), так и к col5 (int) в одной команде. Есть какой-нибудь способ это сделать?
print(dataframe[dataframe['col3'] != 'Y' amp; dataframe['col5'] < 6]) #generates an error
Результат, который я ожидаю от этого:
col1 col2 col3 col4 col5
0 A 10 X 45 3
3 B 10 X 56 4
6 C 10 X 87 4
10 D 20 X 43 4
#
# 78 is max in group A, but ignored as col5 is 6 (we need < 6)
# Similarly, 89 is max in group D, but ignored as col3 is Y.
Прошу прощения, если я делаю что-то не так. Я совсем новичок в этом.
Спасибо.
Ответ №1:
Я не разработчик python, но, по моему мнению, вы делаете это неправильно. Вместо структуры списка у вас должен быть список структуры. Затем вы можете начать работать с таким списком.
Это пример решения, так что, вероятно, это можно было бы сделать гораздо более плавным способом:
data = {
'col1': ['A','A','A','B','B','B','C','C','C','D','D','D'],
'col2': [10,20,30,10,20,30,10,20,30,10,20,30],
'col3': ['X','X','X','X','Y','X','X','X','Y','Y','X','X'],
'col4': [45,23,78,56,12,34,87,54,43,89,43,12],
'col5': [3,4,6,4,3,2,4,3,5,3,4,6]
}
newData = [];
for i in range(len(data['col1'])):
newData.append({'col1' : data['col1'][i], 'col2' : data['col2'][i], 'col3' : data['col3'][i], 'col4' : data['col4'][i], 'col5' : data['col5'][i]})
withoutY = list(filter(lambda d: d['col3'] != 'Y', newData))
lessThen5 = list(filter(lambda d: d['col5'] < 5, withoutY))
values = set(map(lambda d: d['col1'], lessThen5))
groupped = [[d1 for d1 in lessThen5 if d1['col1']==d2] for d2 in values]
result = [];
for i in range(len(groupped)):
result.append(max(groupped[i], key = lambda g: g['col4']))
sortedResult = sorted(result, key = lambda r: r['col1'])
print (sortedResult)
Результат:
[
{'col1': 'A', 'col2': 10, 'col3': 'X', 'col4': 45, 'col5': 3},
{'col1': 'B', 'col2': 10, 'col3': 'X', 'col4': 56, 'col5': 4},
{'col1': 'C', 'col2': 10, 'col3': 'X', 'col4': 87, 'col5': 4},
{'col1': 'D', 'col2': 20, 'col3': 'X', 'col4': 43, 'col5': 4}
]
Комментарии:
1. Привет @Grzegorz У меня нет данных в формате dict, указанном в вопросе. Я просто поделился этим, чтобы другие могли получить данные и использовать их для анализа моей проблемы. У меня есть данные в формате фрейма данных pandas, и мне нужно выработать решение на основе этого.
Ответ №2:
Хорошо, я на самом деле не заметил. Итак, я попробовал что-то вроде этого:
#fd is a filtered data
fd=data.query('col3 != "Y"').query('col5 < 6')
# or fd=data[data.col3 != 'Y'][data.col5 < 6]
#m is max for col4 grouped by col1
m=fd.groupby('col1')['col4'].max()
Это сгруппирует по col1 и получит максимум из col4, но в результате мы получим 2 столбца (col1 и col4).
Я не знаю, чего ты хочешь добиться.
Если вы хотите иметь всю строку, вот код:
result=fd[lambda x: x.col4 == m.get(x.col1).values]
Вам нужно быть осторожным, потому что у вас не всегда будет одна строка для «col1».
Например, для данных
data = pd.DataFrame({
'col1': ['A','A','A','A','B','B','B','B','C','C','C','D','D','D'],
'col2': [20,10,20,30,10,20,20,30,10,20,30,10,20,30],
'col3': ['X','X','X','X','X','X','Y','X','X','X','Y','Y','X','X'],
'col4': [45,45,23,78,45,56,12,34,87,54,43,89,43,12],
'col5': [1,3,4,6,1,4,3,2,4,3,5,3,4,6]})
Результатом будет:
col1 col2 col3 col4 col5
0 A 20 X 45 1
1 A 10 X 45 3
5 B 20 X 56 4
8 C 10 X 87 4
12 D 20 X 43 4
Кроме того, если вы хотите иметь обычный индекс вместо …, 8, 9 12, вы можете использовать «where» вместо «query».