我想提取数据帧‘B’中第一个和最后一个位置所指示的子序列. 我想出的算法是:

  1. 找出位于A位置的B行
  2. 找到位置的相对位置(即移动位置以使其从0开始)
  3. 启动一个for循环,使用相对位置作为范围来提取子序列.

上述算法的问题在于运行时.我需要一种替代方法来编译代码,比现有的方法更快.

Desired output:

first last sequences
  3   5  ACA
  8  12  CGGAG
105 111  ACCCCAA
115 117  TGT

Used data frames:

import pandas as pd
A = pd.DataFrame({'first.sequence': ['AAACACCCGGAG','ACCACACCCCAAATGTGT'
                   ],'first':[1,100], 'last':[12,117]})

B = pd.DataFrame({'first': [3,8,105,115], 'last':[5,12,111,117]})

推荐答案

一种解决方案可能如下所示:

out = pd.merge_asof(B, A, on=['last'], direction='forward',
                    suffixes=('','_y'))

out.loc[:,['first','last']] = \
    out.loc[:,['first','last']].sub(out.first_y, axis=0)

out = out.assign(sequences=out.apply(lambda row: 
          row['first.sequence'][row['first']:row['last']+1], 
          axis=1)).drop(['first.sequence','first_y'], axis=1)

out.update(B)
print(out)

   first  last sequences
0      3     5       ACA
1      8    12     CGGAG
2    105   111   ACCCCAA
3    115   117       TGT

Explanation

  • 首先,使用df.merge_asofB中的first值与A中的first值进行匹配.即3, 81匹配,105, 115100匹配.现在我们知道哪个字符串(序列)需要拆分,也知道字符串从哪里开始,例如,从索引1100开始,而不是从正常的0开始.
  • 我们使用这最后一点信息来找出字符串片应该在哪里开始和结束.所以,我们做out.loc[:,['first','last']].sub(out.first_y, axis=0)个.例如,我们将3重置为2(负1),并将105重置为5(负out.loc[:,['first','last']].sub(out.first_y, axis=0)).
  • 现在,我们可以使用df.apply来获取每个序列的字符串片,实质上是循环遍历每一行.(如果您的切片以相同的索引开始和结束,我们可能会使用Series.str.slice.
  • 最后,我们将结果赋给out(作为列sequences),删除不再需要的列,然后使用df.update"重置"列firstlast.

Python-3.x相关问答推荐

如何使用regex将电话号码和姓名从文本字符串中分离出来

如何将参数/值从测试方法传递给pytest的fixture函数?

为什么我无法在django中按月筛选事件?

链接列未延伸到数据框的末尾

Django中自动设置/更新字段

如何查找以开头并替换的字符串

asyncio.as_completed() 应该接受 `Iterable`,但如果输入是 `Generator` 就会崩溃?

以不规则频率识别数据框日期时间列上缺失的日期,并用关联值填充它们

Tkinter IntVar 返回 PY_VAR0 而不是值

为什么 f-strings 比 str() 更快地解析值?

Python 3.9.8 使用 Black 并导入 `typed_ast.ast3` 失败

使用 pytest.fixture 返回模拟对象的正确方法

cv2 python 没有 imread 成员

python asyncio - 如何等待取消的屏蔽任务?

判断 dict.items() 中的成员资格的时间复杂度是多少?

用 numpy nan 查找列表的最大值

Python的max函数有多高效

对字节进行按位运算

同步调用协程

将 Python SIGINT 重置为默认信号处理程序