python3 也计算滑动中索引位置的平均值的计数器 window
python3 counter that also averages index location in a sliding window
我有一个列表和一个字符串:
anchors=['a','b']
mystring = 'aerdsbewsabsdsasdbs'
我想遍历 mystring
中的每个字母,如果我 "hit" 一个锚点,请跟踪出现在 "prior" 之前 2 个字母和之后 2 个字母的字母"post"。
所以我想要的输出将是一个列表列表,格式为:
[[prior letters, anchor, post letters],
prior letters, anchor, post letters]]
对于每个锚点。这可以很容易地在 mystring
内的 letters
上使用 Counter()
来实现,但我想按平均索引位置对结果输出进行排序。
因此,对于每个前面的字母,我想计算它在每个锚点的 2 个字母内出现的次数,并根据锚点的索引位置的平均值进行排序。在我的锚 'a' 示例中,它看起来像:
prior letters = {s:(2,-1), w:(1,-2), d:(1,-2)}
anchor = 'a'
post letters = {e:(1,1), r:(1,2), b:(1,1), s:(2,1.5), d:(1,2)}
其中前字母和 post 字母的每个键值对采用以下形式:
letter:(count,avg_index)
letter=2
滑动window里面的字母
count = 对于每个anchor
,字母在滑动中出现了多少次window
avg_index = 字母相对于每个锚点的平均索引位置,例如 (-1.5) 表示字母出现在位置 -1 和 -2,平均值为 -1.5。
我正在努力完成代码,是否有更好的数据结构可以帮助我?
不是完整答案,但评论范围太窄。
我测试了这段代码:
import pandas as pd
anchors=['a','b']
mystring = 'aerdsbewsabsdsasdbs'
df = pd.DataFrame(columns=['letter', 'match_anchor', '2_letters_before', '2_letters_afer'])
for letter in mystring:
df = df.append( pd.DataFrame([[letter, letter in anchors]], columns=['letter', 'match_anchor']) )
df['2_letters_before'] = df['letter'].shift(2)
df['2_letters_afer'] = df['letter'].shift(-2)
df = df[df['match_anchor'] == True]
df = df.reset_index(drop=True)
print(df)
输出为:
letter match_anchor 2_letters_before 2_letters_afer
0 a True NaN r
1 b True d w
2 a True w s
3 b True s d
4 a True d d
5 b True s NaN
关键是我不理解你的数据。使用当前输出,我想我已经接近您的期望了。但是,你能解释更多你想要的预期输出吗?例如,数字 (2,-1) 对字母 's'/anchor 'a' 意味着什么?
prior letters = {s:(2,-1), w:(1,-2), d:(1,-2)}
anchor = 'a'
post letters = {e:(1,1), r:(1,2), b:(1,1), s:(2,1.5), d:(1,2)}
编辑:
好吧,这不是一个非常 pythonic 的代码,但我已经设法用 pandas 做到了。
第一步:我正在构建一个 DataFrame,其中的字母与 window 中的锚点 + 字母匹配。
然后,我构建了一个包含所有要查找的字母的列表。我确实遍历这些字母来计算它们+计算索引。
输出不是字典,但我只打印了值。它可以轻松编辑以满足您的需求。
import pandas as pd
import numpy as np
anchors=['a','b']
mystring = 'aerdsbewsabsdsasdbs'
# Building the DataFrame for calculations:
df = pd.DataFrame(columns=['letter', 'match_anchor'])
for letter in mystring:
df = df.append( pd.DataFrame([[letter, letter in anchors]], columns=['letter', 'match_anchor']) )
df['2_let_bef'] = df['letter'].shift(2)
df['1_let_bef'] = df['letter'].shift(1)
df['1_let_aft'] = df['letter'].shift(-1)
df['2_let_aft'] = df['letter'].shift(-2)
df = df[df['match_anchor'] == True]
print(df)
# Getting the list of letters to look to:
let = pd.concat([df['2_let_bef'],
df['1_let_bef'],
df['2_let_aft'],
df['1_let_aft'],], ignore_index=True)
let = let.dropna().unique().tolist()
print('list of letters to look to:', let, '\n')
# looping through
for letter in anchors:
print('\nAnchor=', letter)
pf_anchor = df[df['letter'] == letter]
# checking 'before'
for l in let:
count = len(pf_anchor[pf_anchor['2_let_bef'] == l]) + \
len(pf_anchor[pf_anchor['1_let_bef'] == l])
index_avg = -2*len(pf_anchor[pf_anchor['2_let_bef'] == l]) - \
len(pf_anchor[pf_anchor['1_let_bef'] == l])
if count > 0:
index_avg = index_avg/count
print('(before)', l, ":", (count,index_avg))
for l in let:
# checking 'after'
count = len(pf_anchor[pf_anchor['2_let_aft'] == l]) + \
len(pf_anchor[pf_anchor['1_let_aft'] == l])
index_avg = 2*len(pf_anchor[pf_anchor['2_let_aft'] == l]) + \
len(pf_anchor[pf_anchor['1_let_aft'] == l])
if count > 0:
index_avg = index_avg/count
print('(after)', l, ":", (count,index_avg))
输出:
Anchor= a
(before) d : (1, -2.0)
(before) w : (1, -2.0)
(before) s : (2, -1.0)
(after) d : (1, 2.0)
(after) s : (2, 1.5)
(after) r : (1, 2.0)
(after) e : (1, 1.0)
(after) b : (1, 1.0)
Anchor= b
(before) d : (2, -1.5)
(before) s : (3, -1.6666666666666667)
(before) a : (1, -1.0)
(after) d : (1, 2.0)
(after) w : (1, 2.0)
(after) s : (2, 1.0)
(after) e : (1, 1.0)
我能够在没有 pandas/numpy 的情况下编写它以获得更 pythonic 的答案,但接受了 Oliviers,因为他首先得到它并且它有效。
from collections import Counter, defaultdict
from statistics import mean
mytext = 'sldksfjksljdkljasflkjsfdjkldfslkjsfdsaljkdfsljkbfdsjlkdfs'
anchors = ['k','s']
out = []
letters = []
amount=0
avgindex=0
for anchor in anchors:
anchordict = {anchor:(amount,avgindex)}
letterindex = defaultdict(list)
for i,letter in enumerate(mytext):
if anchor==letter:
z=-2
for letter in mytext[i-2:i]:
letterindex[letter].append(z)
z=z+1
anchordict[anchor] = (anchordict[anchor][0]+1,anchordict[anchor][1]+1)
out.append(anchordict)
for k,v in letterindex.items():
letterindex[k] = mean(v)
for k,v in letterindex.items():
letters.append([anchor,k,v])
letters.sort(key=lambda tup: tup[2])
print(out)
print(letters)
我有一个列表和一个字符串:
anchors=['a','b']
mystring = 'aerdsbewsabsdsasdbs'
我想遍历 mystring
中的每个字母,如果我 "hit" 一个锚点,请跟踪出现在 "prior" 之前 2 个字母和之后 2 个字母的字母"post"。
所以我想要的输出将是一个列表列表,格式为:
[[prior letters, anchor, post letters],
prior letters, anchor, post letters]]
对于每个锚点。这可以很容易地在 mystring
内的 letters
上使用 Counter()
来实现,但我想按平均索引位置对结果输出进行排序。
因此,对于每个前面的字母,我想计算它在每个锚点的 2 个字母内出现的次数,并根据锚点的索引位置的平均值进行排序。在我的锚 'a' 示例中,它看起来像:
prior letters = {s:(2,-1), w:(1,-2), d:(1,-2)}
anchor = 'a'
post letters = {e:(1,1), r:(1,2), b:(1,1), s:(2,1.5), d:(1,2)}
其中前字母和 post 字母的每个键值对采用以下形式:
letter:(count,avg_index)
letter=2
滑动window里面的字母
count = 对于每个anchor
,字母在滑动中出现了多少次window
avg_index = 字母相对于每个锚点的平均索引位置,例如 (-1.5) 表示字母出现在位置 -1 和 -2,平均值为 -1.5。
我正在努力完成代码,是否有更好的数据结构可以帮助我?
不是完整答案,但评论范围太窄。 我测试了这段代码:
import pandas as pd
anchors=['a','b']
mystring = 'aerdsbewsabsdsasdbs'
df = pd.DataFrame(columns=['letter', 'match_anchor', '2_letters_before', '2_letters_afer'])
for letter in mystring:
df = df.append( pd.DataFrame([[letter, letter in anchors]], columns=['letter', 'match_anchor']) )
df['2_letters_before'] = df['letter'].shift(2)
df['2_letters_afer'] = df['letter'].shift(-2)
df = df[df['match_anchor'] == True]
df = df.reset_index(drop=True)
print(df)
输出为:
letter match_anchor 2_letters_before 2_letters_afer
0 a True NaN r
1 b True d w
2 a True w s
3 b True s d
4 a True d d
5 b True s NaN
关键是我不理解你的数据。使用当前输出,我想我已经接近您的期望了。但是,你能解释更多你想要的预期输出吗?例如,数字 (2,-1) 对字母 's'/anchor 'a' 意味着什么?
prior letters = {s:(2,-1), w:(1,-2), d:(1,-2)}
anchor = 'a'
post letters = {e:(1,1), r:(1,2), b:(1,1), s:(2,1.5), d:(1,2)}
编辑: 好吧,这不是一个非常 pythonic 的代码,但我已经设法用 pandas 做到了。 第一步:我正在构建一个 DataFrame,其中的字母与 window 中的锚点 + 字母匹配。 然后,我构建了一个包含所有要查找的字母的列表。我确实遍历这些字母来计算它们+计算索引。 输出不是字典,但我只打印了值。它可以轻松编辑以满足您的需求。
import pandas as pd
import numpy as np
anchors=['a','b']
mystring = 'aerdsbewsabsdsasdbs'
# Building the DataFrame for calculations:
df = pd.DataFrame(columns=['letter', 'match_anchor'])
for letter in mystring:
df = df.append( pd.DataFrame([[letter, letter in anchors]], columns=['letter', 'match_anchor']) )
df['2_let_bef'] = df['letter'].shift(2)
df['1_let_bef'] = df['letter'].shift(1)
df['1_let_aft'] = df['letter'].shift(-1)
df['2_let_aft'] = df['letter'].shift(-2)
df = df[df['match_anchor'] == True]
print(df)
# Getting the list of letters to look to:
let = pd.concat([df['2_let_bef'],
df['1_let_bef'],
df['2_let_aft'],
df['1_let_aft'],], ignore_index=True)
let = let.dropna().unique().tolist()
print('list of letters to look to:', let, '\n')
# looping through
for letter in anchors:
print('\nAnchor=', letter)
pf_anchor = df[df['letter'] == letter]
# checking 'before'
for l in let:
count = len(pf_anchor[pf_anchor['2_let_bef'] == l]) + \
len(pf_anchor[pf_anchor['1_let_bef'] == l])
index_avg = -2*len(pf_anchor[pf_anchor['2_let_bef'] == l]) - \
len(pf_anchor[pf_anchor['1_let_bef'] == l])
if count > 0:
index_avg = index_avg/count
print('(before)', l, ":", (count,index_avg))
for l in let:
# checking 'after'
count = len(pf_anchor[pf_anchor['2_let_aft'] == l]) + \
len(pf_anchor[pf_anchor['1_let_aft'] == l])
index_avg = 2*len(pf_anchor[pf_anchor['2_let_aft'] == l]) + \
len(pf_anchor[pf_anchor['1_let_aft'] == l])
if count > 0:
index_avg = index_avg/count
print('(after)', l, ":", (count,index_avg))
输出:
Anchor= a
(before) d : (1, -2.0)
(before) w : (1, -2.0)
(before) s : (2, -1.0)
(after) d : (1, 2.0)
(after) s : (2, 1.5)
(after) r : (1, 2.0)
(after) e : (1, 1.0)
(after) b : (1, 1.0)
Anchor= b
(before) d : (2, -1.5)
(before) s : (3, -1.6666666666666667)
(before) a : (1, -1.0)
(after) d : (1, 2.0)
(after) w : (1, 2.0)
(after) s : (2, 1.0)
(after) e : (1, 1.0)
我能够在没有 pandas/numpy 的情况下编写它以获得更 pythonic 的答案,但接受了 Oliviers,因为他首先得到它并且它有效。
from collections import Counter, defaultdict
from statistics import mean
mytext = 'sldksfjksljdkljasflkjsfdjkldfslkjsfdsaljkdfsljkbfdsjlkdfs'
anchors = ['k','s']
out = []
letters = []
amount=0
avgindex=0
for anchor in anchors:
anchordict = {anchor:(amount,avgindex)}
letterindex = defaultdict(list)
for i,letter in enumerate(mytext):
if anchor==letter:
z=-2
for letter in mytext[i-2:i]:
letterindex[letter].append(z)
z=z+1
anchordict[anchor] = (anchordict[anchor][0]+1,anchordict[anchor][1]+1)
out.append(anchordict)
for k,v in letterindex.items():
letterindex[k] = mean(v)
for k,v in letterindex.items():
letters.append([anchor,k,v])
letters.sort(key=lambda tup: tup[2])
print(out)
print(letters)