#python #python-3.x #pandas #dataframe #sorting
#python #python-3.x #pandas #фрейм данных #сортировка
Вопрос:
Рассмотрим ниже df:
In [3771]: df = pd.DataFrame({'A': ['a'] * 11,
'B': ['b'] * 11,
'C': ['C1', 'C1', 'C2','C1', 'C3', 'C3', 'C2', 'C3', 'C3', 'C2', 'C2'],
'D': ['D1', 'D2', 'D1', 'D3', 'D3', 'D2', 'D4', 'D4', 'D1', 'D2', 'D3'],
'E': [{'value': '4', 'percentage': None}, {'value': 5, 'percentage': None}, {'value': 12, 'percentage': None}, {'value': 5, 'percentage': None}, {'value': '12', 'percentage': None}, {'value': 'N/A', 'percentage': None}, {}, {'value': 19, 'percentage': None}, {'value': 12, 'percentage': None}, {'value': 11, 'percentage': None}, np.nan],
'F':[{'value': 72, 'percentage': None}, {'value': 72, 'percentage': None}, {'value': 66, 'percentage': None}, {'value': 62, 'percentage': None}, {'value': 66, 'percentage': None}, {'value': 16, 'percentage': None}, {'value': 67, 'percentage': None}, {'value': 67, 'percentage': None}, {'value': 66, 'percentage': None}, {'value': 54, 'percentage': None}, {'value': 78, 'percentage': None}]})
In [3779]: df
Out[3898]:
A B C D E F
0 a b C1 D1 {'value': '4', 'percentage': None} {'value': 72, 'percentage': None}
1 a b C1 D2 {'value': 5, 'percentage': None} {'value': 72, 'percentage': None}
2 a b C2 D1 {'value': 12, 'percentage': None} {'value': 66, 'percentage': None}
3 a b C1 D3 {'value': 5, 'percentage': None} {'value': 62, 'percentage': None}
4 a b C3 D3 {'value': '12', 'percentage': None} {'value': 66, 'percentage': None}
5 a b C3 D2 {'value': 'N/A', 'percentage': None} {'value': 16, 'percentage': None}
6 a b C2 D4 {} {'value': 67, 'percentage': None}
7 a b C3 D4 {'value': 19, 'percentage': None} {'value': 67, 'percentage': None}
8 a b C3 D1 {'value': 12, 'percentage': None} {'value': 66, 'percentage': None}
9 a b C2 D2 {'value': 11, 'percentage': None} {'value': 54, 'percentage': None}
10 a b C2 D3 NaN {'value': 78, 'percentage': None}
Я pivot
выше df:
In [3776]: x = df.pivot(['B', 'C', 'D'], 'A', ['E', 'F'])
In [3781]: x
Out[3900]:
E F
A a a
B C D
b C1 D1 {'value': '4', 'percentage': None} {'value': 72, 'percentage': None}
D2 {'value': 5, 'percentage': None} {'value': 72, 'percentage': None}
D3 {'value': 5, 'percentage': None} {'value': 62, 'percentage': None}
C2 D1 {'value': 12, 'percentage': None} {'value': 66, 'percentage': None}
D2 {'value': 11, 'percentage': None} {'value': 54, 'percentage': None}
D3 NaN {'value': 78, 'percentage': None}
D4 {} {'value': 67, 'percentage': None}
C3 D1 {'value': 12, 'percentage': None} {'value': 66, 'percentage': None}
D2 {'value': 'N/A', 'percentage': None} {'value': 16, 'percentage': None}
D3 {'value': '12', 'percentage': None} {'value': 66, 'percentage': None}
D4 {'value': 19, 'percentage': None} {'value': 67, 'percentage': None}
Я хочу отсортировать самый внутренний столбец, который предназначен D
для каждой группы внешних столбцов B
и C
основан на многоуровневом столбце с индексом (E, a)
в порядке убывания на основе value
ключа из dict.
Редактировать:
dict
Может иметь value
ключ со смешанными типами данных. Это может быть int, str, NaN или просто недоступно.
Ожидаемый результат:
E F
A a a
B C D
b C1 D2 {'value': 5, 'percentage': None} {'value': 72, 'percentage': None}
D3 {'value': 5, 'percentage': None} {'value': 62, 'percentage': None}
D1 {'value': '4', 'percentage': None} {'value': 72, 'percentage': None}
C2 D1 {'value': 12, 'percentage': None} {'value': 66, 'percentage': None}
D2 {'value': 11, 'percentage': None} {'value': 54, 'percentage': None}
D4 {} {'value': 67, 'percentage': None}
D3 NaN {'value': 78, 'percentage': None}
C3 D4 {'value': 19, 'percentage': None} {'value': 67, 'percentage': None}
D1 {'value': 12, 'percentage': None} {'value': 66, 'percentage': None}
D3 {'value': '12', 'percentage': None} {'value': 66, 'percentage': None}
D2 {'value': 'N/A', 'percentage': None} {'value': 16, 'percentage': None}
Ответ №1:
Решение с помощью помощника MultiIndex column
, созданного Series.str.get
, затем сортировка по DataFrame.sort_values
и последнее удаление вспомогательного столбца:
x[('new', 'a')] = pd.to_numeric(x[('E','a')].str.get('value'), errors='coerce')
lvl = x.index.names[:-1]
order = 'desc'
x = (x.sort_values(lvl [('new', 'a')],ascending=[True] * len(lvl) [order == 'asc'])
.drop(('new', 'a'), axis=1))
print (x)
E
A a
B C D
b C1 D2 {'value': 5, 'percentage': None}
D3 {'value': 5, 'percentage': None}
D1 {'value': '4', 'percentage': None}
C2 D1 {'value': 12, 'percentage': None}
D2 {'value': 11, 'percentage': None}
D3 NaN
D4 {}
C3 D4 {'value': 19, 'percentage': None}
D1 {'value': 12, 'percentage': None}
D3 {'value': '12', 'percentage': None}
D2 {'value': 'N/A', 'percentage': None}
F
A a
B C D
b C1 D2 {'value': 72, 'percentage': None}
D3 {'value': 62, 'percentage': None}
D1 {'value': 72, 'percentage': None}
C2 D1 {'value': 66, 'percentage': None}
D2 {'value': 54, 'percentage': None}
D3 {'value': 78, 'percentage': None}
D4 {'value': 67, 'percentage': None}
C3 D4 {'value': 67, 'percentage': None}
D1 {'value': 66, 'percentage': None}
D3 {'value': 66, 'percentage': None}
D2 {'value': 16, 'percentage': None}
Комментарии:
1. знаете ли вы, почему это решение выдает ошибку?
x.sort_values(by=('E', 'a'), key=lambda x: x.get('value'))
или эквивалентx.sort_values(by=('E', 'a'), key=lambda x: x['value'])
2. @IoaTzimas — Возможно, новая функциональность, поэтому некоторые ошибки.
3. @jezrael Не могли бы вы, пожалуйста, сделать это решение немного общим в том смысле, что мне не нужно жестко кодировать имена столбцов
B
,C
иD
? Мне всегда нужно сортировать самый внутренний столбец, который естьD
, а остальные столбцы (B
иC
) могут быть одинаковыми.4. @jezrael Спасибо за помощь. Есть еще один случай, должен ли я добавить для него образцы данных?
5. @jezrael Это работает очень хорошо. Спасибо за всю помощь.