Сортировка уникальных последовательных пар элементов в кадре данных панд - PullRequest
0 голосов
/ 24 сентября 2019

Ранее я задавал несколько недостающий вопрос, который можно найти здесь .Спеша написать этот вопрос, я понял, что на самом деле поставил не ту проблему.И отличный ответ не отражает проблему, которую я пытаюсь решить.Увы, вот я снова пытаюсь.

Мои данные содержатся в панде (в столбце).Ради этой проблемы предположим, что это выглядит примерно так (где мы используем небольшую версию небольшого представления кадра данных):

array([['a', 125183.195],
       ['t', 125529.335],
       ['t', 125626.555],
       ['a', 125632.485],
       ['h', 125755.395],
       ['h', 125868.105],
       ['e', 125892.82],
       ['e', 126007.555],
       [' ', 126113.25],
       [' ', 126221.61],
       ['w', 126695.285],
       ['w', 126827.34],
       ['-', 127149.21],
       ['-', 127269.435],
       ['s', 127668.525],
       ['h', 127789.04],
       ['s', 127800.76],
       ['h', 127887.645]])

Давайте назовем весь этот массив D.

Теперь у меня есть около 2000 таких массивов, и каждый из них имеет в среднем около 300-400 рядов.Так что здесь нет большой необходимости в производительности.

Возвращаясь к нашему списку MWE, мы заинтересованы только в упорядочении массива , используя только первый столбец :

array(['a', 't', 't', 'a', 'h', 'h', 'e', 'e', ' ', ' ', 'w', 'w','-', '-', 's', 'h', 's', 'h'])

Теперь порядок элементов в списке должен быть структурированным, как у последовательных пар (но по причинам сбора данных они не являются).Итак, вот отсортированный столбец, к которому мы стремимся:

array(['a', 'a', 't', 't', 'h', 'h', 'e', 'e', ' ', ' ', 'w', 'w','-', '-', 's', 's', 'h', 'h'])

В этом проблема: столбцы содержат почти последовательных пары элементов (числа в приведенном выше примере), но некоторые из нихвышли из строя и должны быть возвращены своему партнеру (см. выше).Чтобы еще больше усугубить проблему, второй столбец в D является числовым, и эти записи уникальны, и они также должны следовать новому порядку.Итак, конечный результат, к которому мы стремимся, для этого минимального примера:

array([['a', 125183.195],
       ['a', 125632.485],
       ['t', 125529.335],
       ['t', 125626.555],
       ['h', 125755.395],
       ['h', 125868.105],
       ['e', 125892.82],
       ['e', 126007.555],
       [' ', 126113.25],
       [' ', 126221.61],
       ['w', 126695.285],
       ['w', 126827.34],
       ['-', 127149.21],
       ['-', 127269.435],
       ['s', 127668.525],
       ['s', 127800.76],
       ['h', 127789.04],
       ['h', 127887.645]])

Следовательно, важен вертикальный порядок пар символов.Место, где они появляются в массиве, является ключом к моей проблемной области, поэтому их можно перемещать только в соответствующие пары, но, кроме перемещения члена каждой пары, член первой пары не может двигаться.

Несколько вещейдля наблюдения:

  • Производительность на самом деле не является проблемой, поскольку их нужно будет отсортировать только один раз.
  • Образец не в порядке не соответствует и в каждом столбце многое меняется, важно то, что каждый элемент сопоставляется с его партнером.
    • Элементы в первом столбце всегда отображаются в виде пар.

Я ищу помощь с методом, который может сортировать строки D в требуемый порядок пары.Спасибо и извинения за мой первый неверно заданный вопрос.

Ответы [ 2 ]

2 голосов
/ 24 сентября 2019

Если я правильно понял, вы хотите использовать в качестве ключ увеличивающееся значение каждый раз, когда вы видите букву два раза, то есть:

from itertools import count
import pandas as pd

df = pd.DataFrame(data=data, columns=['letters', 'value'])

def lookup(v, d={}, c=count()):
    if v in d:
       return d.pop(v)
    else:
       d[v] = next(c)
       return d[v]

df['key'] = df.letters.map(lookup)

print(df)

Вывод

   letters       value  key
0        a  125183.195    0
1        t  125529.335    1
2        t  125626.555    1
3        a  125632.485    0
4        h  125755.395    2
5        h  125868.105    2
6        e  125892.820    3
7        e  126007.555    3
8           126113.250    4
9           126221.610    4
10       w  126695.285    5
11       w  126827.340    5
12       -  127149.210    6
13       -  127269.435    6
14       s  127668.525    7
15       h  127789.040    8
16       s  127800.760    7
17       h  127887.645    8

После того, как у вас есть ключевой столбец, просто отсортируйте его (и отбросил):

print(print(df.sort_values(by='key', kind='mergesort').drop('key', axis=1)))

Выход

   letters       value
0        a  125183.195
3        a  125632.485
1        t  125529.335
2        t  125626.555
4        h  125755.395
5        h  125868.105
6        e  125892.820
7        e  126007.555
8           126113.250
9           126221.610
10       w  126695.285
11       w  126827.340
12       -  127149.210
13       -  127269.435
14       s  127668.525
16       s  127800.760
15       h  127789.040
17       h  127887.645

Чтобы сохранить порядок появления, используйте стабильную сортировку , такую ​​как сортировка слиянием (указывается параметром kind='merge-sort').

1 голос
/ 24 сентября 2019

Если вы хотите отсортировать по столбцу строк, вы можете сделать что-то вроде:

df = pd.DataFrame([['a', 125183.195],
       ['t', 125529.335],
       ['t', 125626.555],
       ['a', 125632.485],
       ['h', 125755.395],
       ['h', 125868.105],
       ['e', 125892.82],
       ['e', 126007.555],
       [' ', 126113.25],
       [' ', 126221.61],
       ['w', 126695.285],
       ['w', 126827.34],
       ['-', 127149.21],
       ['-', 127269.435],
       ['s', 127668.525],
       ['h', 127789.04],
       ['s', 127800.76],
       ['h', 127887.645]], columns=["letter", "number"])

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

  • Создать новый фрейм данных
  • Создать список индексов, помещенных в фрейм
  • Зацикливаться на добавляемых элементах фрейма и первых встречающихся парах, покаизбегая индексов, которые уже были включены
df_2 = pd.DataFrame(columns=["letter", "number"])
indexes = []
for i in range(len(df)):

    if i not in indexes:
        df_2 = df_2.append( df.loc[i,:])
        letter = df.loc[i,"letter"]
        indexes.append(i)

        for j in range(i+1, len(df)):
            if ((df.loc[j,"letter"] == df.loc[i,"letter"]) and (j not in indexes)):

                df_2 = df_2.append( df.loc[j,:])
                indexes.append(j)
                break;

Вывод:

array([['a', 125183.195],
       ['a', 125632.485],
       ['t', 125529.335],
       ['t', 125626.555],
       ['h', 125755.395],
       ['h', 125868.105],
       ['e', 125892.82],
       ['e', 126007.555],
       [' ', 126113.25],
       [' ', 126221.61],
       ['w', 126695.285],
       ['w', 126827.34],
       ['-', 127149.21],
       ['-', 127269.435],
       ['s', 127668.525],
       ['s', 127800.76],
       ['h', 127789.04],
       ['h', 127887.645]], dtype=object)

Надеюсь, это помогло.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...