我有一个像这样的矩阵列的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 ['结果'] = 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']]
答案 0 :(得分:2)
我会这样做。
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
答案 1 :(得分:1)
这是我的解决方案,需要一些工作。
策略如下:获取一个与当前列具有相同值但移动了一个位置的新列。
然后,检查一列是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
还有最后一个元素的问题,但如果您决定遵循此策略,我相信您可以考虑如何处理它;)
答案 2 :(得分:0)
您可以使用DataFrame.drop(labels, axis)
从DataFrame中删除行。要获取要删除的标签列表,我首先会得到符合您标准的对列表。使用列表中的标签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