2

我正在尝试根据特定列的内容将 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 行分析器分析此函数时,我得到以下结果。

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数组的方法?

4

1 回答 1

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 倍。

于 2019-01-25T10:00:55.897 回答