pandas过滤连续的行

时间:2015-09-29 20:18:32

标签: python pandas

我有一个像这样的矩阵列的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']]

3 个答案:

答案 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中删除行。要获取要删除的标签列表,我首先会得到符合您标准的对列表。使用列表中的标签labelsisAB功能

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