python - 在 Pandas 数据框中查找 asc/desc 序列

标签 python pandas

我正在尝试构建一个有助于简化研究工作的工具,似乎需要检测一列中的数据何时具有递增序列,而另一列中的数据何时具有递增/降序序列。

有没有一种干净的方法来检查行中是否有序列,而不必编写像这样遍历行的状态机 https://stackoverflow.com/a/52679427/5045375 ?编写这样一段代码必须检查一列中的值是否在递增(无间隙),而另一列中的值是否为 asc/desc(无间隙)。我完全能够做到这一点,我只是想知道我的 Pandas 工具箱中是否有我遗漏的东西。

这里有一些例子来阐明我的意图,

import pandas as pd 
from collections import namedtuple

QUERY_SEGMENT_ID_COLUMN = 'Query Segment Id'
REFERENCE_SEGMENT_ID_COLUMN = 'Reference Segment Id'

def dataframe(data):
    columns = [QUERY_SEGMENT_ID_COLUMN, REFERENCE_SEGMENT_ID_COLUMN]
    return pd.DataFrame(data, columns=columns)

# No sequence in either column. No results
data_without_pattern = [[1, 2], [7, 0], [3, 6]]

# Sequence in first column, but no sequence in second column. No results
data_with_pseodo_pattern_query = [[1, 2], [2, 0], [3, 6]]

# Sequence in second column, but no sequence in first column. No results
data_with_pseudo_pattern_reference = [[1, 2], [7, 3], [3, 4]]

# Broken sequence in first column, sequence in second column. No results
data_with_pseudo_pattern_query_broken = [[1, 2], [3, 3], [7, 4]]

# Sequence occurs in both columns, asc. Expect results
data_with_pattern_asc = [[1, 2], [2, 3], [3, 4]]

# Sequence occurs in both columns, desc. Expect results
data_with_pattern_desc = [[1, 4], [2, 3], [3, 2]]

# There is a sequence, and some noise. Expect results
data_with_pattern_and_noise = [[1, 0], [1, 4], [1, 2], [1, 3], [2, 3], [3, 4]]

在第一个例子中,没有任何模式,
print(dataframe(data_without_pattern))
   Query Segment Id  Reference Segment Id
0                 1                     2
1                 7                     0
2                 3                     6

第二个示例在查询列中具有升序的 id 序列,但在引用列中没有,
print(dataframe(data_with_pseodo_pattern_query))
   Query Segment Id  Reference Segment Id
0                 1                     2
1                 2                     0
2                 3                     6

第三个示例与前一个示例相同,但针对引用列。
print(dataframe(data_with_pseudo_pattern_reference))
   Query Segment Id  Reference Segment Id
0                 1                     2
1                 7                     3
2                 3                     4

在这里,引用列中有一个升序,而查询列中的 id 也按升序排列,但存在间隙,因此不会产生任何结果
print(dataframe(data_with_pseudo_pattern_query_broken))
   Query Segment Id  Reference Segment Id
0                 1                     2
1                 3                     3
2                 7                     4

这里有两个“完美”的例子,其中查询列按升序排列,不间断,引用列分别按降序和升序排列。结果在意料之中。
print(dataframe(data_with_pattern_asc))
   Query Segment Id  Reference Segment Id
0                 1                     2
1                 2                     3
2                 3                     4

print(dataframe(data_with_pattern_desc))
   Query Segment Id  Reference Segment Id
0                 1                     4
1                 2                     3
2                 3                     2

最终,一个数据不太干净但仍然存在所需模式的案例
print(dataframe(data_with_pattern_and_noise))
   Query Segment Id  Reference Segment Id
0                 1                     0
1                 1                     4
2                 1                     2
3                 1                     3
4                 2                     3
5                 3                     4

这个最新的案例可能需要进一步解释。我的目标是返回类似于 q=(1, 3), r=(2, 4) 的东西。 ,例如(start, end)来自相应列(不是索引)的值。

我在想是否有可能做一个很好的 group_by 序列行动,但我没有只见树木不见森林。

我认为这个问题具有社区值(value),因为我找不到类似的问题,即有人在多列的行中寻找模式。

编辑:来自评论的案例(@code-different)

对于数据框,
data_with_multiple_contiguous_sequences = [[1, 1], [2, 2], [3, 3], [0, 4], [1, 5], [2, 6], [3, 7], [4, 8]]

   Query Segment Id  Reference Segment Id
0                 1                     1
1                 2                     2
2                 3                     3
3                 0                     4
4                 1                     5
5                 2                     6
6                 3                     7
7                 4                     8

目标是识别两个序列。这意味着我们想要让出 q1=(1, 3), r1=(1, 3), q2=(0, 4), r2=(4, 8) .

最佳答案

如果我理解正确的话,您的问题是孤岛问题的变体。每个具有可接受间隙的单调(增加或减少)子序列将形成一个岛。例如,给定一个系列 s :

s   island
--  ------
0   1
0   1
1   1
3   2        # gap > 1, form new island
4   2
2   3        # stop increasing, form new island
1   3 
0   3

概括地说:每当当前行和前一行之间的差距超出 [-1, 1] 范围时,就会形成一个新岛。

Query Segment Id 上应用此间隙岛算法和 Reference Segment Id :
Query Segment Id  Q Island    Reference Segment Id  R Island    Q-R Intersection
----------------  --------    --------------------  --------    ----------------
1                 1           1                     1           (1, 1)
2                 1           2                     1           (1, 1)
3                 1           3                     1           (1, 1)
0                 2           4                     1           (2, 1)
1                 2           5                     1           (2, 1)
2                 2           6                     1           (2, 1)
3                 2           7                     1           (2, 1)
4                 2           8                     1           (2, 1)
0                 3           9                     1           (3, 1)
qr您正在寻找的范围现在是 Query Segment IdReference Segment Id在每个 Q-R Intersection 的开头和结尾.但最后一个警告:忽略长度为 1 的交集(如最后一个交集)。

代码:
columns = ['Query Segment Id', 'Reference Segment Id']
df = pd.DataFrame(data_with_multiple_contiguous_sequences, columns=columns)

def get_island(col):
    return (~col.diff().between(-1,1)).cumsum()

df[['Q Island', 'R Island']] = df[['Query Segment Id', 'Reference Segment Id']].apply(get_island)

result = df.groupby(['Q Island', 'R Island']) \
            .agg(**{
                'Q Start': ('Query Segment Id', 'first'),
                'Q End': ('Query Segment Id', 'last'),
                'R Start': ('Reference Segment Id', 'first'),
                'R End': ('Reference Segment Id', 'last'),
                'Count': ('Query Segment Id', 'count')
            }) \
            .replace({'Count': 1}, {'Count': np.nan}) \
            .dropna()
result['Q'] = result[['Q Start', 'Q End']].apply(tuple, axis=1)
result['R'] = result[['R Start', 'R End']].apply(tuple, axis=1)

结果:
                   Q Start  Q End  R Start  R End  Count       Q       R
Q Island R Island                                                       
1        1               1      3        1      3      3  (1, 3)  (1, 3)
2        1               0      4        4      8      5  (0, 4)  (4, 8)

关于python - 在 Pandas 数据框中查找 asc/desc 序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61175786/

相关文章:

Python:获取字典中索引的键

python - 列出字典 : Even items as keys, 奇数项作为值

python - 修改 pandas 数据框中的行子集

python - 对 pandas 中相同的列名进行分组会将 '.1' 添加到列中

python - numpy 数组可以是 pandas 数据框中的元素吗?

python - 切片和赋值唯一顺序索引的多索引 Pandas 数据框

java - 我们如何将 TensorFlow 2.x 模型导入到 Java 中?

python - 分词器扩展提取

python - 最好的 python 库,当用户提交时,使 textarea 在网页中安全

python - pandas groupby 并在多列上应用函数