我有一份excel表(彭博数据许可证输出)我用
读到import pandas as pd
raw_data = pd.read_excel('my-file.xlsx')
根据返回的数据量,有一列(START-OF-FILE
)和不同的行数。
我对两行之间的数据感兴趣,特别是START-OF-DATA
和END-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('|')
将管道分隔数据分隔成一个新数据帧的单独列?
答案 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()
方法。