![](/img/trans.png)
[英]Filtering pandas dataframe for all rows where index is consecutive +/-1
[英]pandas filtering consecutive rows
我有一個像這樣的Matrix colum的Dataframe
11034-A
11034-B
1120-A
1121-A
112570-A
113-A
113.558
113.787-A
113.787-B
114-A
11691-A
11691-B
117-A RRS
12 X R
12-476-AT-A
12-476-AT-B
我只想過濾只有在連續時以A或B結尾的矩陣,所以在上面的例子中,11034-A和11034-B,113.787-A和113.787-B,11691-A和11691-B,12 -476-AT-A和12-476-AT-B
我編寫了將比較這兩個字符串並返回True或False的函數,問題是我無法看到如何將/ applymap應用於連續的行:
def isAB(stringA, stringB):
if stringA.endswith('A') and stringB.endswith('B') and stringA[:-1] == stringB[:-1]:
return True
else:
return False
我試過df ['result'] = isAB(df ['Matrix']。str,df ['Matrix'] .shift()。str)無效我似乎缺乏某種方式我設計的方式
編輯:我認為這有效,看起來我在第一次過於復雜:
df['t'] = (df['Matrix'].str.endswith('A') & df['Matrix'].shift(-1).str.endswith('B')) | (df['Matrix'].str.endswith('B') & df['Matrix'].shift(1).str.endswith('A'))
df['p'] = (df['Matrix'].str[:-1] == df['Matrix'].shift(-1).str[:-1]) | (df['Matrix'].str[:-1] == df['Matrix'].shift(1).str[:-1])
df['e'] = df['p'] & df['t']
final = df[df['e']]
我就是這樣做的。
df['ShiftUp'] = df['matrix'].shift(-1)
df['ShiftDown'] = df['matrix'].shift()
def check_matrix(x):
if pd.isnull(x.ShiftUp) == False and x.matrix[:-1] == x.ShiftUp[:-1]:
return True
elif pd.isnull(x.ShiftDown) == False and x.matrix[:-1] == x.ShiftDown[:-1]:
return True
else:
return False
df['new'] = df.apply(check_matrix, axis=1)
df = df.drop(['ShiftUp', 'ShiftDown'], axis=1)
print df
版畫
matrix new
0 11034-A True
1 11034-B True
2 1120-A False
3 1121-A False
4 112570-A False
5 113-A False
6 113.558 False
7 113.787-A True
8 113.787-B True
9 114-A False
10 11691-A True
11 11691-B True
12 117-A RRS False
13 12 X R False
14 12-476-AT-A True
15 12-476-AT-B True
這是我的解決方案,需要一些工作。
策略如下:獲取一個新列,該列具有與當前列相同的值但移位了一個位置。
然后,檢查一列是A還是B而另一列是B還是A只是一個問題。
假設您的矩陣列稱為“column_name”。
然后:
myl = ['11034-A',
'11034-B',
'1120-A',
'1121-A',
'112570-A',
'113-A',
'113.558',
'113.787-A',
'113.787-B',
'114-A',
'11691-A',
'11691-B',
'117-A RRS',
'12 X R',
'12-476-AT-A',
'12-476-AT-B']
#toy data frame
mydf = pd.DataFrame.from_dict({'column_name':myl})
#get a new series which is the same one as the original
#but the first entry contains "nothing"
new_series = pd.Series( ['nothing'] +
mydf['column_name'][:-1].values.tolist() )
#add it to the original dataframe
mydf['new_col'] = new_series
然后定義一個簡單的函數:
def do_i_want_this_row(x,y):
left_char = x[-1]
right_char = y[-1]
return ((left_char == 'A') & (right_char == 'B')) or ((left_char == 'B') & (right_char=='A'))
瞧:
print mydf[mydf.apply(lambda x: do_i_want_this_row( x.column_name, x.new_col), axis=1)]
column_name new_col
1 11034-B 11034-A
2 1120-A 11034-B
8 113.787-B 113.787-A
9 114-A 113.787-B
11 11691-B 11691-A
15 12-476-AT-B 12-476-AT-A
還有最后一個元素的問題,但我相信如果您決定遵循這個策略,您可以想一想如何處理它;)
您可以使用DataFrame.drop(labels, axis)
從DataFrame中刪除行。 要獲取要刪除的標簽列表,我首先會得到符合您標准的對列表。 使用列表labels
上面的labels
和您的isAB
功能,
pairs = zip(labels[:-1], labels[1:])
delete_pairs = filter(isAB, pairs)
delete_labels = []
for a,b in delete_pairs:
delete_labels.append(a)
delete_labels.append(b)
檢查delete_labels
以確保您正確地將它們放在一起,
print(delete_labels)
最后,刪除行。 將DataFrame作為x
,
x.drop(delete_labels) # or x.drop(delete_labels, axis) if appropriate
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.