Python Pandas根据条目的字符串值过滤行

时间:2015-06-19 22:41:22

标签: python pandas bloomberg

我有一份excel表(彭博数据许可证输出)我用

读到
import pandas as pd
raw_data = pd.read_excel('my-file.xlsx')

根据返回的数据量,有一列(START-OF-FILE)和不同的行数。

我对两行之间的数据感兴趣,特别是START-OF-DATAEND-OF-DATA。列中的行看起来像

19                                      START-OF-DATA
20  WTS Equity|0|6|WTS|50545|54.440000|54.000000|5...
21  XOM Equity|0|6|XOM|6555175|84.950000|85.300000...
22  SUP Equity|0|6|SUP|27405|19.250000|19.200000|1...
23                                        END-OF-DATA

具有不同的行数(不总是20到22)。如何将列中的行仅过滤为单元格之间的数据,即raw_data['START-OF-FILE']['START-OF-DATA' : 'END-OF-DATA']。然后使用str.split('|')将管道分隔数据分隔成一个新数据帧的单独列?

2 个答案:

答案 0 :(得分:2)

>>> import pandas as pd
>>> df = pd.DataFrame(['abcdef', 'START-OF-DATA', 'g|h|i', 'j|k|l', 'm|n|o', 'END-OF-DATA', 'pqrstu', columns=['A']])
>>> df
               A
0         abcdef
1  START-OF-DATA
2          g|h|i
3          j|k|l
4          m|n|o
5    END-OF-DATA
6         pqrstu
>>> start, end = df[df['A'].str.contains('(START|END)-OF-DATA')].index.tolist()
>>> pd.DataFrame(df[start+1:end]['A'].str.split('|').tolist(), columns=['A', 'B', 'C'])
   A  B  C
2  g  h  i
3  j  k  l
4  m  n  o

答案 1 :(得分:1)

我写了一个函数来为你做这个:

def select_data(data, column, start, stop):

    store = []

    for idx, item in enumerate(data[column]):
        if item in [start, stop]:
            store.append(idx)

    output = pd.DataFrame(list(data[column][store[0]+1:store[1]].str.split('|')))

    return output

输出:

In [231]: df = pd.DataFrame(['a|b|c|d']*20, columns=['test-col']);

In [232]: df.ix[5, ['test-col']] = 'START'

In [233]: df.ix[17, ['test-col']] = 'STOP'

In [234]: df
Out[234]: 
   test-col
0   a|b|c|d
1   a|b|c|d
2   a|b|c|d
3   a|b|c|d
4   a|b|c|d
5     START
6   a|b|c|d
7   a|b|c|d
8   a|b|c|d
9   a|b|c|d
10  a|b|c|d
11  a|b|c|d
12  a|b|c|d
13  a|b|c|d
14  a|b|c|d
15  a|b|c|d
16  a|b|c|d
17     STOP
18  a|b|c|d
19  a|b|c|d

In [235]: test = filter_data(df, 'test-col', 'START','STOP')

In [236]: test
Out[236]: 
    0  1  2  3
0   a  b  c  d
1   a  b  c  d
2   a  b  c  d
3   a  b  c  d
4   a  b  c  d
5   a  b  c  d
6   a  b  c  d
7   a  b  c  d
8   a  b  c  d
9   a  b  c  d
10  a  b  c  d

为了跟进这里,我对两个功能进行了一些时间测试。结果如下:

In [1]: import pandas as pd

In [2]: import timeit

In [3]: df = pd.DataFrame(['a|b|c|d']*10000, columns=['test-col'])

In [4]: df.ix[2654, ['test-col']] = 'START'

In [5]: df.ix[9000, ['test-col']] = 'STOP'

In [6]: %paste
def func_1(data, column, start, stop):

        store = []

        for idx, item in enumerate(data[column]):
                if item in [start, stop]:
                        store.append(idx)

        output = pd.DataFrame(list(data[column][store[0]+1:store[1]].str.split('|')))

        return output


def func_2(df):

        start, end = df[df['test-col'].str.contains('START|STOP')].index.tolist()
        output = pd.DataFrame(df[start+1:end]['test-col'].str.split('|').tolist())

        return output

## -- End pasted text --

In [7]: %timeit func_1(df, 'test-col', 'START','STOP')
100 loops, best of 3: 8.95 ms per loop

In [8]: %timeit func_2(df)
100 loops, best of 3: 13.3 ms per loop

我的假设func_1()快于func_2()的原因是因为使用正则表达式进行模式匹配的.contains()方法。