Как поддерживать порядок при выборе строк в фрейме данных pandas?

Я хочу выбрать строки в определенном порядке, указанном в списке. Например

Этот фрейм данных

a=[['car',1],['bike',3],['jewel',2],['tv',5],['phone',6]]

df=pd.DataFrame(a,columns=['items','quantity'])

>>> df
   items  quantity
0    car         1
1   bike         3
2  jewel         2
3     tv         5
4  phone         6

Я хочу получить строки с таким порядком ['tv','car','phone'], то есть сначала тв, потом машина, а потом телефон. Я пробовал этот метод, но он не поддерживает порядок

arr=['tv','car','phone']

df.loc[df['items'].isin(arr)]

   items  quantity
0    car         1
3     tv         5
4  phone         6
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
16
0
7 761
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

IIUC Categorical

df=df.loc[df['items'].isin(arr)]
df.iloc[pd.Categorical(df['items'],categories=arr,ordered=True).argsort()]
Out[157]: 
   items  quantity
3     tv         5
0    car         1
4  phone         6

Или reindex: обратите внимание, что это не сохранит предыдущий индекс, и если исходный индекс имеет значение, вы должны использовать Categorical (упоминается Энди Л., если у вас есть дубликаты в элементах, reindex будет не удалось)

df.set_index('items').reindex(arr).reset_index()
Out[160]: 
   items  quantity
0     tv         5
1    car         1
2  phone         6

Или цикл через arr

pd.concat([df[df['items']==x] for x in arr])
Out[171]: 
   items  quantity
3     tv         5
0    car         1
4  phone         6
reindex потерпит неудачу, если его реальные данные будут дублироваться items ?
Andy L. 19.06.2019 03:44

@ЭндиЛ. yelp это будет, Однако он может проверить другие методы, которые я предоставил :-)

BENY 19.06.2019 03:45

прохладно! просто прошу убедиться, что я не ошибаюсь reindex :)

Andy L. 19.06.2019 03:48
Ответ принят как подходящий

Вот ненавязчивое решение с использованием Index.get_indexer, которое не требует установки индекса:

df.iloc[pd.Index(df['items']).get_indexer(['tv','car','phone'])]

   items  quantity
3     tv         5
0    car         1
4  phone         6

Обратите внимание: если это станет частым явлением (я имею в виду «индексацию» со списком в столбце), вам лучше превратить этот столбец в индекс. Бонусные баллы, если вы сортируете его.

df2 = df.set_index('items')
df2.loc[['tv','car','phone']]  

       quantity
items          
tv            5
car           1
phone         6

Вот еще один сорт, в котором используется .loc.

# Move items to the index, select, then reset.
df.set_index("items").loc[arr].reset_index()

Или другой, который не меняет индекс.

df.loc[df.reset_index().set_index("items").loc[arr]["index"]]

Обратите внимание, что .loc не сохраняет порядок в мультииндексированных сериях/фреймах данных. Это несоответствие с .loc между одиночными и мультииндексированными кадрами данных считается ошибка, а решение является частью вех Pandas 1.1.0.

Ivan De Paz Centeno 16.07.2020 14:00

Почему бы нет:

>>> df.iloc[df.loc[df['items'].isin(arr), 'items'].apply(arr.index).sort_values().index]
   items  quantity
3     tv         5
0    car         1
4  phone         6
>>> 

Я бы создал словарь от arr и map до items и dropna, sort_values

d = dict(zip(arr, range(len(arr))))

Out[684]: {'car': 1, 'phone': 2, 'tv': 0}

df.loc[df['items'].map(d).dropna().sort_values().index]

Out[693]:
   items  quantity
3     tv         5
0    car         1
4  phone         6

merge на помощь:

(pd.DataFrame({'items':['tv','car','phone']})
   .merge(df, on='items')
)

Выход:

   items  quantity
0     tv         5
1    car         1
2  phone         6

df не в порядке массива.

Yaakov Bressler 19.06.2019 17:10

@YaakovBressler Да, и об этом позаботится слияние с фреймом данных, созданным из массива.

Quang Hoang 19.06.2019 17:11

Я не предполагаю, что порядок массива будет важен, но что, если бы это было так? Будет ли способ сохранить это в слиянии?

Yaakov Bressler 19.06.2019 17:16

Я не понимаю. Это цель использования слияния здесь. То есть merge сохранить порядок ДАННОГО массива.

Quang Hoang 19.06.2019 17:18

Порядок массива (не то, что у df)

Yaakov Bressler 19.06.2019 17:29

Да, ПОРЯДОК МАССИВА поддерживается merge. Вы хоть пробовали?

Quang Hoang 19.06.2019 17:30

Понимаю. Моя ошибка, извините. Однако исходный индекс был утерян.

Yaakov Bressler 19.06.2019 17:35

Для выбора всех элементов, существующих на входе df, вот один с searchsorted и должен быть хорошим по производительности -

In [43]: sidx = df['items'].argsort()

In [44]: df.iloc[sidx[df['items'].searchsorted(['tv','car','phone'],sorter=sidx)]]
Out[44]: 
   items  quantity
3     tv         5
0    car         1
4  phone         6

Почему бы не искать индекс, фильтровать и изменять порядок:

df['new_order'] = df['items'].apply(lambda x: arr.index(x) if x in arr else -1)

df_new = df[df['new_order']>=0].sort_values('new_order')


   items  quantity  new_order
3     tv         5          0
0    car         1          1
4  phone         6          2

Другие вопросы по теме