Python datatable (или pandas): сложная сортировка фрейма данных на основе двух столбцов

#python #pandas #dataframe #sorting #datatable

#python #pandas #фрейм данных #сортировка #datatable

Вопрос:

ВХОДНЫЕ ДАННЫЕ

 from datatable import dt

C1 = ['a', 'a', 'b', 'c']
C2 = ['b', 'c', 'a', 'a']

df1 = dt.Frame(C1=C1, C2=C2)
  

df1:

    | C1  C2
--   --  --
 0 | a   b 
 1 | a   c 
 2 | b   a 
 3 | c   a 
  

ВЫХОДНЫЕ ДАННЫЕ

 C1 = ['a', 'b', 'a', 'c']
C2 = ['b', 'a', 'c', 'a']

df2 = dt.Frame(C1=C1, C2=C2)
  

df2:

    | C1  C2
--   --  --
 0 | a   b 
 1 | b   a 
 2 | a   c 
 3 | c   a 
  

Преобразование объекта datatable в объект pandas:

 df = df.to_pandas()
  

Описание вопроса:

Я стараюсь сделать это как можно более понятным. Если возникнут какие-либо вопросы, я с удовольствием объясню подробнее. Образец данных содержит уникальные значения ‘a’, ‘b’, ‘c’ в столбцах C1 и C2. Каждая комбинация значений в C1 и C2 встречается только один раз (например, C1 = ‘a’ amp; C2 = ‘b’ в первой строке df1). Для большинства комбинаций существует «пара», что означает обратную комбинацию (в данном случае к вышеупомянутому примеру: C1 = ‘b’ amp; C2 = ‘a’ в третьей строке). Как я могу упорядочить этот фрейм данных, чтобы все «пары» были рядом друг с другом? Этот желаемый результат отображается в df2. Я предпочитаю использовать datatable вместо pandas. Но если у кого-то есть решение в pandas, это было бы одинаково полезно для меня.

Я надеюсь, что этот вопрос удовлетворяет рекомендациям SO. Если нет, я рад его улучшить. Большое вам спасибо.

Редактировать: кажется, мои данные образца были слишком упрощенными. Это менее упрощенный набор данных:

 C1 = ['a', 'a', 'b', 'c']
C2 = ['b', 'c', 'a', 'a']
Values = [5, 10, 15, 20]

df1 = dt.Frame(C1=C1, C2=C2, Values=Values)
  

Ответ №1:

Это то, что ты ищешь:

 >>> from datatable import dt, f, sort, ifelse
>>> df1 = dt.Frame(C1=['a', 'a', 'b', 'c'], 
                   C2=['b', 'c', 'a', 'a'], 
                   Values=[5, 10, 15, 20])
>>> df1[:, :, sort(ifelse(f.C1<f.C2, f.C1, f.C2), 
                   ifelse(f.C1<f.C2, f.C2, f.C1))]
   | C1  C2  Values
--   --  --  ------
 0 | a   b        5
 1 | b   a       15
 2 | a   c       10
 3 | c   a       20

[4 rows x 3 columns]
  

Здесь мы сортируем фрейм по 2 вычисляемым столбцам, первый — это минимум C1 и C2, а второй — максимум C1 и C2.

Комментарии:

1. Да, это то, что я ищу. Вы позволите мне использовать ваше решение в последующем вопросе. Я уверен, что вы упомянуты.

Ответ №2:

После преобразования в pandas , мы можем попробовать sort_values после numpy.sort

 import numpy as np 
df1 = df1.to_pandas()

out = df1.iloc[pd.DataFrame(np.sort(df1.values,1)).sort_values([0,1]).index]
Out[54]: 
  C1 C2
0  a  b
2  b  a
1  a  c
3  c  a
  

Комментарии:

1. Спасибо за ваш ответ. Я получаю следующую ошибку: TypeError: ‘<‘ не поддерживается между экземплярами ‘float’ и ‘str’. Я обновил свой вопрос, чтобы лучше отражать реальный набор данных. Извините за мою ошибку.

Ответ №3:

Попробуйте это:

 import pandas as pd

C1 = ['a', 'a', 'b', 'c']
C2 = ['b', 'c', 'a', 'a']
Values = [5, 10, 15, 20]

df = pd.DataFrame({'C1': C1, 'C2': C2, 'Values': Values})
srt = df.apply(lambda x: ','.join(sorted(x[['C1', 'C2']].values)),axis=1)
df.loc[srt.argsort(),:]

  

Комментарии:

1. Спасибо за ваш ответ. Я получаю следующую ошибку: TypeError: ‘<‘ не поддерживается между экземплярами ‘float’ и ‘str’. Я обновил свой вопрос, чтобы лучше отражать реальный набор данных. Извините за мою ошибку.

2. Я изменил ответ