在导入到pandas之前,请跳过每个指定的行

时间:2015-10-14 20:17:37

标签: python python-3.x pandas

我有一个数据文件,我需要跳过某些行。

(1 1),skip,this
skip,this,too
1,2,3
4,5,6
7,8,9
10,11,12
(1 2),skip,this
skip,this,too
...

他们会在每4个数据条目后重复播放。我尝试了这篇文章Pandas: ignore all lines following a specific string when reading a file into a DataFrame中的内容,但是没有任何内容被跳过,而是将数据框转换为MultiIndex。

我尝试使用startswith()进行循环并附加到列表中,但是,数据正在输入到单个列中。

我正在尝试获取此输出:

1,2,3
4,5,6
7,8,9
10,11,12

有多个文件,每个文件包含超过7M行。我正在寻找一种快速,内存有效的方法来实现这一目标。

我尝试的是创建一个列表以跳过行0,1,然后再次6, 7。是否有可能实现这一目标?

5 个答案:

答案 0 :(得分:1)

我的建议是预先擦洗文件:

with open("file.csv") as rp, open("outfile.csv", 'w') as wp:
    for line in rp:
        if 'skip' not in line:
            wp.write(line)

答案 1 :(得分:1)

假设您想要在两行之后跳过四行的部分,只需跳过两行并从csv阅读器中获取一行四行:

from itertools import islice, chain
import pandas as pd
import csv


def parts(r):
    _, n = next(r), next(r)
    while n:
        yield islice(r, 4)
        _, n = next(r, ""), next(r, "")
            _, n = next(r, ""), next(r, "")


with open("test.txt")as f:
        r = csv.reader(f)
        print(pd.DataFrame(list(chain.from_iterable(parts(r)))))

输出:

    0   1   2
0   1   2   3
1   4   5   6
2   7   8   9
3  10  11  12

或者将链对象传递给pd.DataFrame.from_records

with open("test.txt")as f:
    r = csv.reader(f)
    print(pd.DataFrame.from_records(chain.from_iterable(parts(r))))

    0   1   2
0   1   2   3
1   4   5   6
2   7   8   9
3  10  11  12

使用消耗配方使用函数跳过行的更通用的方法:

from itertools import islice, chain
from collections import deque
import pandas as pd
import csv

def consume(iterator, n):
    "Advance the iterator n-steps ahead. If n is none, consume entirely."
    # Use functions that consume iterators at C speed.
    if n is None:
        # feed the entire iterator into a zero-length deque
        deque(iterator, maxlen=0)
    else:
        # advance to the empty slice starting at position n
        next(islice(iterator, n, n), None)


def parts(r, sec_len, skip):
    consume(r,skip)
    for sli in iter(lambda: list(islice(r, sec_len)), []):
        yield sli
        consume(r, skip)


with open("test.txt")as f:
    r = csv.reader(f)
    print(pd.DataFrame.from_records((chain.from_iterable(parts(r, 4, 2)))))

最后一个选项是写入StringIo对象并传递:

from io import StringIO
def parts(r, sec_len, skip):
    consume(r, skip)
    for sli in iter(lambda: list(islice(r, sec_len)), []):
        yield "".join(sli)
        consume(r, skip)


with open("test.txt")as f:
    so = StringIO()
    so.writelines(parts(f, 4, 2))
    so.seek(0)
    print(pd.read_csv(so, header=None))

答案 2 :(得分:1)

一种方法是生成要跳过的行号列表,因此请在此处使用方法确定文件中的行数:Count how many lines are in a CSV Python?

然后执行以下操作:

In [16]:
import io
​import pandas as pd
t="""(1 1),skip,this
skip,this,too
1,2,3
4,5,6
7,8,9
10,11,12
(1 2),skip,this
skip,this,too"""
# generate initial list, using 10 her but you can get the number of rows using another metho
a = list(range(10))
# generate the pairs of rows to skips in steps
rows = sorted(a[::6] + a[1::6])
# now read it in
pd.read_csv(io.StringIO(t), skiprows=rows, header=None)

Out[16]:
    0   1   2
0   1   2   3
1   4   5   6
2   7   8   9
3  10  11  12

答案 3 :(得分:1)

由于你有一个重复模式(折腾两行,保持四行),我可能会这样做:

from io import BytesIO
with open("skipper.csv", "rb") as fp:
    lines = (line for i,line in enumerate(fp) if i % 6 >= 2)
    df = pd.read_csv(BytesIO(b''.join(lines)), header=None)

给了我

>>> df
    0   1   2
0   1   2   3
1   4   5   6
2   7   8   9
3  10  11  12

答案 4 :(得分:-1)

我会想要动态地进行过滤:

import subprocess
import pandas as pd

cmd = "awk '(NR - 1) % 6 > 1' test.csv"
proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
df = pd.read_csv(proc.stdout, header=None)

awk命令将跳过每组6中的前两行。由于过滤是在流式基础上完成的,因此这是非常高效的内存,并且由于过滤是在单独的过程中完成的,因此它将是也很快。