首页 > 解决方案 > 将二维数组的字符串表示形式从 CSV 列读取到二维 numpy 数组中

问题描述

我有一个 pandas 数据框,其中一列包含与灰度图像中的像素数据相对应的 2D numpy 数组。这些 2D numpy 数组的形状为(480, 640)(490, 640)。数据框有其他包含其他信息的列。然后我通过 pandas 的to_csv()函数从中生成一个 csv 文件。现在我的问题是:我的 2D numpy 数组在我的 CSV 中都显示为字符串,那么我怎样才能读回它们并将它们再次转换为 2D numpy 数组?

我知道 StackOverflow 上有类似的问题,但我找不到任何真正关注 2D numpy 数组的问题。它们似乎主要是关于一维 numpy 数组,并且提供的解决方案似乎不起作用。

任何帮助是极大的赞赏。

更新:

根据要求,我在下面添加了一些代码来澄清我的问题。

# Function to switch images to grayscale format
grayscale(img):
  cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Iterating through my dataframe (called data), reading all image files, making them grayscale and then adding them to my collection.
grayscale_images = []
for index, row in data.iterrows():
  img_path = row['Image path']
  cv_image = cv2.imread(img_path)
  gray = grayscale(cv_image)
  grayscale_images.append(gray)

# Make numpy array elements show without truncation
np.set_printoptions(threshold=sys.maxsize)

# Adding a new column to the dataframe containing each image's numpy array corresponding to pixels
data['Image data'] = grayscale_images

因此,当我在其他列上完成此操作和其他操作时,我将数据框导出为 CSV,如下所示:

data.to_csv('new_dataset.csv', index=False)

在另一个 Jupyter 笔记本中,我尝试读取我的 CSV 文件,然后提取图像的 numpy 数组以将它们作为输入提供给卷积神经网络,作为监督训练的一部分。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import sys
import re

data = pd.read_csv('new_dataset.csv')
# data.head() -- It looks fine here

# Config to make numpy arrays display in their entirety without truncation
np.set_printoptions(threshold=sys.maxsize)

# Checking if I can extract a 2D numpy array for conversion from a cell.
# That's where I notice it's a string, and I'm having trouble turning it back to a 2D numpy array
image_arr = data.iloc[0,0]

但是,我坚持将我的字符串类型表示从我的 CSV 文件转换回 2D numpy 数组,尤其(490, 640)是在我将数据帧导出到 CSV 之前的形状。

标签: pythonarrayspandasnumpycsv

解决方案


用数组字符串构造一个 csv:

In [385]: arr = np.empty(1, object)                                             
In [386]: arr[0]=np.arange(12).reshape(3,4)                                     
In [387]: S = pd.Series(arr,name='x')                                           
In [388]: S                                                                     
Out[388]: 
0    [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]
Name: x, dtype: object
In [389]: S.to_csv('series.csv')                                                
/usr/local/bin/ipython3:1: FutureWarning: The signature of `Series.to_csv` was aligned to that of `DataFrame.to_csv`, and argument 'header' will change its default value from False to True: please pass an explicit value to suppress this warning.
  #!/usr/bin/python3
In [390]: cat series.csv                                                        
0,"[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]"

加载它:

In [391]: df = pd.read_csv('series.csv',header=None)                            
In [392]: df                                                                    
Out[392]: 
   0                                                1
0  0  [[ 0  1  2  3]\n [ 4  5  6  7]\n [ 8  9 10 11]]

In [394]: astr=df[1][0]                                                         
In [395]: astr                                                                  
Out[395]: '[[ 0  1  2  3]\n [ 4  5  6  7]\n [ 8  9 10 11]]'

解析数组的字符串表示:

In [396]: astr.split('\n')                                                      
Out[396]: ['[[ 0  1  2  3]', ' [ 4  5  6  7]', ' [ 8  9 10 11]]']

In [398]: astr.replace('[','').replace(']','').split('\n')                      
Out[398]: [' 0  1  2  3', '  4  5  6  7', '  8  9 10 11']
In [399]: [i.split() for i in _]                                                
Out[399]: [['0', '1', '2', '3'], ['4', '5', '6', '7'], ['8', '9', '10', '11']]
In [400]: np.array(_, int)                                                      
Out[400]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

不能保证这是最漂亮最干净的解析,但它可以让您了解您必须做的工作。我正在重新发明轮子,但搜索副本的时间太长了。

如果可能,尽量避免将这样的数据框保存为 csv。csv 格式适用于干净的 2d 表,由分隔符分隔的简单一致的列。

在大多数情况下,避免这样的数据帧/系列。Series 可以有 object dtype。并且每个对象元素都可以是复杂的,例如列表、字典或数组。但我认为pandas没有特殊功能可以处理这些情况。

numpy也有对象 dtypes(如 my arr),但列表通常同样好,如果不是更好的话。构造这样的数组可能很棘手。这样一个数组上的数学是命中或未命中。对象数组的迭代比列表的迭代慢。

===

re可能也有效。例如用逗号替换空格:

In [408]: re.sub('\s+',',',astr)                                                
Out[408]: '[[,0,1,2,3],[,4,5,6,7],[,8,9,10,11]]'

还是不太对。有前导逗号会窒息eval


推荐阅读