将 dataframe/array 从 32 * 32 列乘以 16 行整形并转换为 (32 * 16) 乘以 32

Reshape and transform a dataframe/array from 32 * 32 columns by 16 rows to (32 * 16) by 32

我有 16 张 32x32px 图像的灰度图像数据存储在 pandas 数据框中。每个数据行代表一张图像的序列化像素数据,因此数据帧有 1024 列。

我想重塑数据以不仅恢复原始图像大小,而且将所有重塑图像串联(水平)。

因此第一行将如下所示:前 32 列:图像 1 - 第 1 行像素,后 32 列:图像 2 - 第 1 行像素,...

第二行将如下所示:前 32 列:图像 1 - 第 2 行像素,后 32 列:图像 2 - 第 2 行像素,...

基本上,我想将我的数据帧从 (32 * 32) x 16 重塑为 (32 * 16) x 32。之后我想使用此数据通过 PIL 创建图像。

有没有优雅的方法来做到这一点?我现在有点不知所措,因为我对完全使用 pandas 和 Python 还是陌生的。我不期待一个完整的答案,但如果你至少能把我推向正确的方向就好了。

这里是三个不同的函数,第一个使用Pandas方法(堆叠)。第二个使用常规 python 列表,逐行构建结果。最后一个使用 numpy 重塑。

numpy 重塑方法的效率是其他方法的两倍,几乎所有计算时间实际上都花在了将 DataFrame 转换为 numpy 数组格式,然后再返回 pandas。

这里有一个 link to the notebook 如果你想尝试一下代码,我用它来做这个。

def stack_image_df(image_df):
    """
    Performance: 100 loops, best of 5: 19 ms per loop
    """
    # create a MultiIndex indicating Row and Column information for each image
    row_col_index = pd.MultiIndex.from_tuples(
        [(i // 32, i % 32) for i in range(0, 1024)], name=["row", "col"]
    )
    image_df.columns = row_col_index

    image_df.index = range(1, 17)
    image_df.index.name = "Image"

    # Use MultiIndex to reshape data
    return image_df.stack(level=1).T


def build_image_df(image_df):
    """
    Performance: 10 loops, best of 5: 19.2 ms per loop
    """
    image_data = image_df.values.tolist()
    reshaped = []
    for r_num in range(0, 32):
        row = []
        for image_num in range(0, 16):
            # for each image
            for c_num in range(0, 32):
                # get the corresponding index in the raw data
                # and add the pixel data to the row we're building
                raw_index = r_num * 32 + c_num
                pixel = image_data[image_num][raw_index]
                row.append(pixel)
        reshaped.append(row)
    reshaped_df = pd.DataFrame(reshaped)
    return reshaped_df


def reshape_image_df(image_df):
    """
    Performance: 100 loops, best of 5: 9.56 ms per loop
    Note: numpy methods only account for 0.82 ms of this

    """
    return pd.DataFrame(
        np.rot90(np.fliplr(raw_df.to_numpy().reshape(512, 32)))
    )