分区numpy二维数组的优化方法

时间:2019-01-25 09:47:11

标签: arrays python-3.x numpy line-profiler

我正在尝试根据内容将2D numpy数组划分为2个单独的numpy数组 特定列的这是我的代码:

import numpy as np
import pandas as pd

@profile
def partition_data(arr,target_colm):
    total_colms = arr.shape[1]
    target_data = arr[:,target_colm]
    type1_data = []
    type2_data = []
    for i in range(arr.shape[0]):
        if target_data[i]==0:  # if value==0, put in another array
            type1_data = np.append(type1_data,arr[i])
        else:
            type2_data = np.append(type2_data,arr[i])
    type1_data = np.array(type1_data).reshape(int(len(type1_data)/total_colms),total_colms)
    type2_data = np.array(type2_data).reshape(int(len(type2_data)/total_colms),total_colms)
    return type1_data, type2_data

d = pd.read_csv('data.csv').values
x,y = partition_data(d,7)  # check values of 7th column

注意:在我的实验中,我使用了(14359,42)个元素的数组。

现在,当我使用kernprof line profiler对该函数进行概要分析时,会得到以下结果。

Wrote profile results to code.py.lprof
Timer unit: 1e-06 s
Total time: 7.3484 s
File: code2.py
Function: part_data at line 8
Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
     8                                           @profile
     9                                           def part_data(arr,target_col):
    10         1          7.0      7.0      0.0      total_colms = arr.shape[1]
    11         1         14.0     14.0      0.0      target_data = arr[:,target_col]
    12         1          2.0      2.0      0.0      type1_data = []
    13         1          1.0      1.0      0.0      type2_data = []
    14      5161      40173.0      7.8      0.5      for i in range(arr.shape[0]):
    15      5160      39225.0      7.6      0.5          if target_data[i]==6:
    16      4882    7231260.0   1481.2     98.4              type1_data = np.append(type1_data,arr[i])
    17                                                   else:
    18       278      33915.0    122.0      0.5              type2_data = np.append(type2_data,arr[i])
    19         1       3610.0   3610.0      0.0      type1_data = np.array(type1_data).reshape(int(len(type1_data)/total_colms),total_colms)
    20         1        187.0    187.0      0.0      type2_data = np.array(type2_data).reshape(int(len(type2_data)/total_colms),total_colms)
    21         1          3.0      3.0      0.0      return type1_data, type2_data

在这里,一条16行占用大量时间。将来,我将使用的实际数据量会更大。

任何人都可以建议一种更快的分区numpy数组的方法吗?

1 个答案:

答案 0 :(得分:3)

这应该使其速度更快:

def partition_data_vectorized(arr, target_colm):
    total_colms = arr.shape[1]
    target_data = arr[:,target_colm]
    mask = target_data == 0
    type1_data = arr[mask, :]
    type2_data = arr[~mask, :]
    return (
        type1_data.reshape(int(type1_data.size / total_colms), total_colms), 
        type2_data.reshape(int(type2_data.size / total_colms), total_colms))

一些时间:

# Generate some sample inputs:
arr = np.random.rand(10000, 42)
arr[:, 7] = np.random.randint(0, 10, 10000)

%timeit c, d = partition_data_vectorized(arr, 7)
# 2.09 ms ± 200 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit a, b = partition_data(arr, 7)
# 4.07 s ± 102 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

这比非矢量化计算快 2000倍

比较结果:

np.all(b == d)
# Out: True
np.all(a == c)
# Out: True

因此,结果是正确的,只是通过向量化操作用np.append替换for循环和重复的数组创建,速度快了2000倍。