python - Numpy数组切片转置内部数据

标签 python c arrays numpy slice

我正在编写一个 C 扩展来处理 numpy 数组。我写了一个函数来读取和输出 numpy 数组。使用它时,我注意到在输入数组中使用切片时会出现一种奇怪的行为。

读取(boolan)数组的 C 函数:

char **pymatrix_to_CarrayptrsChar(PyArrayObject *arrayin) {
    char **result, *array;
    int i, n, m, j;

    n = arrayin->dimensions[0];
    m = arrayin->dimensions[1];
    result = ptrvectorChar(n, m);

    array = (char *) arrayin->data; /* pointer to arrayin data as int */
    for (i = 0; i < n; i++) {
      result[i] = &array[i * m];
    }
    printArrChar(result, n, m);
    return result;
}

ptrvectorChar 是内存分配函数:

char **ptrvectorChar(long dim1) {
    char **v;
    if (!(v = malloc(dim1 * sizeof(char*)))) {
        PyErr_SetString(PyExc_MemoryError,
              "In **ptrvectorChar. Allocation of memory for character array failed.");
        exit(0);
    }
    return v;
}

打印完成:

void printArrChar(char **arr, int dim1, int dim2) {
    int i, j;
    for (i = 0; i < dim1; i++) {
        for (j = 0; j < dim2; j++) {
            printf("%i ", arr[i][j]);
        }
        printf("\n");
    }
}

我用于重现错误的 python 脚本是:

import numpy as np
import MyExtension
np.random.seed(1)

x = np.array((1,1,1,1,1,1)).astype(bool)
a = np.round(np.random.rand(trialNr, lakeNr)).astype(bool)
aSlicing = a[:, x]

print("a:")
print(a + 0)

print("aSlicing:")
print(aSlicing + 0)

print("C output for a:")
MyExtension.MyFunction(a)

print("C output for aSlicing:")
MyExtension.MyFunction(aSlicing)

输出是:

a:
[[0 1 0 0 0 0]
 [0 0 0 1 0 1]
 [0 1 0 1 0 1]
 [0 0 1 1 0 1]
 [1 1 0 0 0 1]
 [0 0 1 1 1 0]
 [1 1 0 1 1 1]
 [0 1 0 0 1 0]
 [0 0 0 1 0 0]
 [0 0 1 0 1 1]]

aSlicing:
[[0 1 0 0 0 0]
 [0 0 0 1 0 1]
 [0 1 0 1 0 1]
 [0 0 1 1 0 1]
 [1 1 0 0 0 1]
 [0 0 1 1 1 0]
 [1 1 0 1 1 1]
 [0 1 0 0 1 0]
 [0 0 0 1 0 0]
 [0 0 1 0 1 1]]

C output for a:
0 1 0 0 0 0 
0 0 0 1 0 1 
0 1 0 1 0 1 
0 0 1 1 0 1 
1 1 0 0 0 1 
0 0 1 1 1 0 
1 1 0 1 1 1 
0 1 0 0 1 0 
0 0 0 1 0 0 
0 0 1 0 1 1 

C output for aSlicing:
0 0 0 0 1 0 
1 0 0 0 1 0 
1 0 1 0 1 1 
0 0 0 0 0 1 
0 1 0 0 0 1 
0 1 1 1 0 1 
1 0 1 0 0 0 
0 0 0 1 1 1 
0 1 0 1 1 1 
1 0 1 0 0 1 

很容易看出,aaSlicing对于python来说是相同的数组。但是,读取数据的 C 函数将数据视为某种转置。 C 将 aSliced 视为

a.T.reshape((10,6))

有谁知道为什么会出现这个错误以及如何正确规避它?当然,在 C 代码中转置很容易。但是,我希望我的程序能够处理这两种类型的数组。

我更喜欢我的 C 扩展中的解决方案,即我的扩展的用户不必关心他们的输入是否被“切片”。尽管如此,我还是尝试将 aSliced 的深拷贝放入我的扩展中 - 这与 aSliced 的结果相同。

我正在使用 python 3.4 64 位、numpy 1.9.1、Win8 64 位和 Visual Studio 10 64 位 C 编译器。

最佳答案

正如 hpaulj 所指出的,可以使用标志 F_CONTIGUOUS 找出内存结构。我花了很多时间试图找到一种从 C 中读取此标志的方法。据我所知,可以通过评估 trials_array->flags % 2 的值来完成。但是,我没有找到任何对这个问题有明确解释的引用资料。

trials_array->flags 是一个整数。 numpy 标志常量 NPY_C_CONTIGUOUSNPY_F_CONTIGUOUS 等是整数,是 2 的幂。如果 trials_array->flags 的二进制表示中的相应位置为 1,则似乎设置了标志。

即使知道内存结构,读取数组也不像我想的那么简单。我找到了一种更容易的方法将 numpy 数组转换为 C 数组:使用

char *myArray;
PyArrayObject *myArray_Numpy;

PyArray_AsCArray(&myArray_Numpy, (void *) &myArray, myArray_Numpy->dimensions, 2, PyArray_DescrFromType(NPY_BOOL));

//Do something with the array

PyArray_Free(myArray_Numpy, myArray);

我找到了一个使用这些函数的例子 here .

关于python - Numpy数组切片转置内部数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30535467/

相关文章:

python - 调用多个函数并返回集体结果

python - Flask:当用户在执行一个长进程时关闭浏览器时会发生什么?

python - 打印未显示在 ipython 笔记本中

c - 分配一个不同对待的值

python - 预期类型 'str' ,Tuple[str] 在 python3.8 中返回

C - 将信息传输到结构(特别是字符串数组)

c - 一次在多维数组中写入一个字符串 C

C:扫描数组时忽略一个值

c++ - 键/值数组的双调排序

javascript - 简单求和 ng-repeat 列