在pandas数据框中对唯一连续的一对项目进行排序

2024-06-11 06:44:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我以前问过一个有点欠缺的问题,可以在here找到。在我匆忙写下那个问题的时候,我意识到,事实上,我提出了一个错误的问题。而出色的回答并没有反映出我试图解决的问题。唉,我又来了。你知道吗

我的数据包含在dataframe中(列上)。为了解决这个问题,假设它看起来是这样的(在这里我们使用数据帧小视图的numpy版本):

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行按所需的成对顺序排序。感谢并为我的第一个错误的问题道歉。你知道吗


Tags: 数据项目方法目标列表here排序顺序
2条回答

如果要按字符串列排序,可以执行以下操作:

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)

希望这有帮助。你知道吗

如果我理解正确,您希望每次看到一个字母两次时都使用递增值作为键,即:

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

要保留外观顺序,请使用stable sort,例如merge sort(由参数kind='merge-sort'指定)。你知道吗

相关问题 更多 >