我正在处理具有数千行的数据,但是列不均匀,如下所示:

AB  12   43   54

DM  33   41   45   56   33   77  88

MO  88   55   66   32   34

KL  10   90   87   47   23  48  56  12


首先,我想读取列表或数组中的数据,然后找出最长的行的长度。
然后,我将在短行中添加零,使它们等于最长的零,以便可以将它们迭代为2D数组。

我尝试了其他几个类似的问题,但无法解决问题。

我相信Python中有一种方法可以做到这一点。有人可以帮我吗?

最佳答案

我没有找到更简单的方法来找出最大行长度,而是进行一次遍历并找到它。然后,在第二遍中构建2D数组。就像是:

from __future__ import print_function
import numpy as np
from itertools import chain

data = '''AB 12 43 54
DM 33 41 45 56 33 77 88
MO 88 55 66 32 34
KL 10 90 87 47 23 48 56 12'''

max_row_len = max(len(line.split()) for line in data.splitlines())

def padded_lines():
    for uneven_line in data.splitlines():
        line = uneven_line.split()
        line += ['0']*(max_row_len - len(line))
        yield line

# I will get back to the line below shortly, it unnecessarily creates the array
# twice in memory:
array = np.array(list(chain.from_iterable(padded_lines())), np.dtype(object))

array.shape = (-1, max_row_len)

print(array)


打印:

[['AB' '12' '43' '54' '0' '0' '0' '0' '0']
 ['DM' '33' '41' '45' '56' '33' '77' '88' '0']
 ['MO' '88' '55' '66' '32' '34' '0' '0' '0']
 ['KL' '10' '90' '87' '47' '23' '48' '56' '12']]


上面的代码在内存中两次创建数组的意义上是无效的。我会回到它;我想我可以解决这个问题。

但是,numpy数组应该是同质的。您要将字符串(第一列)和整数(所有其他列)放在同一2D数组中。我仍然认为您在这里走错了路,应该重新考虑问题并选择其他数据结构或以其他方式组织数据。我无法为您提供帮助,因为我不知道您想如何使用这些数据。

(我将很快返回创建两次的数组。)



如所承诺的,这是效率问题的解决方案。请注意,我担心的是内存消耗。

    def main():

        with open('/tmp/input.txt') as f:
            max_row_len = max(len(line.split()) for line in f)

        with open('/tmp/input.txt') as f:
            str_len_max = len(max(chain.from_iterable(line.split() for line in f), key=len))

        def padded_lines():
            with open('/tmp/input.txt') as f:
                for uneven_line in f:
                    line = uneven_line.split()
                    line += ['0']*(max_row_len - len(line))
                    yield line

        fmt = '|S%d' % str_len_max
        array = np.fromiter(chain.from_iterable(padded_lines()), np.dtype(fmt))


可以使这段代码更好,但我将由您自己决定。

内存消耗,用memory_profiler在具有1000000行和1到20之间均匀分布的行长度的随机生成的输入文件上测量:

Line #    Mem usage    Increment   Line Contents
================================================
     5   23.727 MiB    0.000 MiB   @profile
     6                             def main():
     7
     8   23.727 MiB    0.000 MiB       with open('/tmp/input.txt') as f:
     9   23.727 MiB    0.000 MiB           max_row_len = max(len(line.split()) for line in f)
    10
    11   23.727 MiB    0.000 MiB       with open('/tmp/input.txt') as f:
    12   23.727 MiB    0.000 MiB           str_len_max = len(max(chain.from_iterable(line.split() for line in f), key=len))
    13
    14   23.727 MiB    0.000 MiB       def padded_lines():
    15                                     with open('/tmp/input.txt') as f:
    16   62.000 MiB   38.273 MiB               for uneven_line in f:
    17                                             line = uneven_line.split()
    18                                             line += ['0']*(max_row_len - len(line))
    19                                             yield line
    20
    21   23.727 MiB  -38.273 MiB       fmt = '|S%d' % str_len_max
    22                                 array = np.fromiter(chain.from_iterable(padded_lines()), np.dtype(fmt))
    23   62.004 MiB   38.277 MiB       array.shape = (-1, max_row_len)


使用代码eumiro的答案,并使用相同的输入文件:

Line #    Mem usage    Increment   Line Contents
================================================
     5   23.719 MiB    0.000 MiB   @profile
     6                             def main():
     7   23.719 MiB    0.000 MiB       with open('/tmp/input.txt') as f:
     8  638.207 MiB  614.488 MiB           arr = np.array(list(it.izip_longest(*[line.split() for line in f], fillvalue='0'))).T


比较内存消耗增量:我更新的代码消耗的内存比eumiro的少16倍(614.488 / 38.273约为16)。

至于速度:我更新的代码为此输入运行3.321s,eumiro的代码运行5.687s,也就是说,我的机器上的速度是我的1.7倍。 (你的旅费可能会改变。)

如果效率是您最关心的问题(如您的评论“嗨,eumiro,我想这会更有效率。”然后更改接受的答案),那么恐怕您接受了效率较低的解决方案。

别误会,eumiro的代码非常简洁,我当然从中学到了很多。如果效率不是我的主要关注点,我也会选择eumiro的解决方案。

关于python - Python-使用行中不均匀的列,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33937624/

10-11 17:45