在 Python 3 中将逗号分隔的字符串转换为 Numpy 数组
Posted
技术标签:
【中文标题】在 Python 3 中将逗号分隔的字符串转换为 Numpy 数组【英文标题】:Converting Comma-Separated String to Numpy Array In Python 3 【发布时间】:2017-09-15 06:31:03 【问题描述】:我正在使用 Python 在 Python 3 中使用 PySerial 从 Arduino 传感器读取数据。
我想使用 PyQtGraph 绘制数据,所以我试图将从传感器读取的字符串(288 个逗号分隔值)转换为 Numpy 数组。但是,我尝试了几种不同的方法,但都没有奏效。
使用此代码从传感器读取数据效果很好:
#Read the line of data from the sensor
line = sensor.readline()
#Decode the line to UTF-8 and print it
lineDecoded = line.decode("UTF-8")
print(lineDecoded)
这给了我正确的输出(288 个逗号分隔值):
137,136,151,145,141,133,145,139,140,145,144,139,143,141,139,136,137,138,137,127,142,135,136,137 ,134,140,127,141,134,128,139,135,136,180,149,147,147,151,156,140,153,143,143,155,163,164,192,250,277 ,282,275,258,258,248,245,231,215,225,195,195,159,186,175,168,171,173,177,185,213,224,228,231,227,219 ,261,229,231,231,250,253,262,276,269,274,274,277,276,272,291,303,351,417,483,500,473,399,315,263,255 ,239,238,244,234,231,231,242,255,272,294,293,299,314,307,306,302,310,319,304,312,327,370,464,507,514,492,425,358,327,313,299,292,291,281,259,245,232,229,224,223,222,216,226,215,211,197,202,199,197,198,193,198,185,190,196,177,198,188,183,201,193,187,159,189,184,186,185,186,185,184,196,195,200,201,198,193,241,189,186,167,179,187,174,188,180,179,169,177,173,172,175,181,175,171,180,175,176,180,184,176,190,182,172,171,179,178,174,188,175,178,167,183,171,168,174,175,171,230,175,177,159,177,170,172,171,173,168,167,169,172,168,171,177,173,167,167,171,163,170,177,172,169,167,163,157,173,161,168,174,162,1 65,171,165,160,160,160,160,160,160,160,161,160,158,160,158,160,158,160,158,158,158,158,158,165,158,158,158,158,158,158,158,155158,158,158155
从那里,我想我只能将 lineDecoded
传递给 PyQtGraph 的 plot
函数,但是在运行这行代码之后
x = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288]
y = [lineDecoded]
#Plot the data
pg.plot(x, y)
我收到了错误Exception: X and Y arrays must be the same shape--got (288,) and (1,).
我尝试使用np.fromstring(lineDecoded)
和np.array(list(lineDecoded)).ravel()
等各种方法转换字符串,然后再将其传递给PyQtGraph,但我尝试过的方法均无效。
关于如何实现这一点的任何想法?
编辑:我已经浏览了答案,但似乎没有一个有效,每个响应的 cmets 中都有详细信息。任何提示都会很棒。
【问题讨论】:
你能打印 y 和 type(y) 吗?输出是什么? 您可以将其拆分为列表,然后拆分为 numpy.array,y = np.array(lineDecoded.split(","))
。但实际上并不需要,您可以将其用作绘图列表。
【参考方案1】:
line.decode()
返回一个字符串(str
),而不是list
。所以你得到的是一个单一的实体,而不是 288 个值。
Python 有一个与字符串相关联的方法,该方法将获取一个字符串并将其拆分为组件部分。调用.split()
方法并为其提供要拆分的子字符串,在本例中为“,”应该可以解决问题。
#Read the line of data from the sensor
line = sensor.readline()
#Decode the line to UTF-8 and print it
lineDecoded = line.decode("UTF-8")
values = [int(i) for i in lineDecoded.split(',')] # <<< this should work
# added a list
# comprehension to
# convert values to integers
x = range(1,289) # <<< this is preferred if you need
# a range of numbers from 1 to 288
y = values
#Plot the data
pg.plot(x, y)
注意:正如@umutto 在上面的评论中提到的那样,出于绘图目的,不需要将值转换为 numpy 数组。列表应该就可以了。
但是,如果由于某种原因你发现你想要/需要一个数组:
y = np.array(values)
【讨论】:
谢谢 - 我在 split 函数上使用了你的建议并得到了TypeError: cannot perform reduce with flexible type pyqtgraph
,所以我将代码修改为 lineDecoded = lineDecoded[:-2]
(删除多余的数字)和 yValues = lineDecoded.split(",")
y = np.array(yValues).astype(np.int)
。错误消息现在消失了,但 PyQtGraph 弹出窗口在打开时崩溃并且不显示任何数据。任何想法为什么会发生这种情况(在 Jupyter 中)?
@AggroCrag 的问题:您能否使用简单、定义明确的数据生成您尝试生成的图形的简化版本?即向 pg.plot(x, y) 输入每个的简短列表: x = [1, 2, 3] y = [5, 6, 7] 我经常通过创建众所周知的数据来查找问题的根源如果那行得通。如果是这样,那么我开始查看我的真实数据。如果没有,那么我开始查看我的实现(即 Jupyter 是否设置为显示 PyQtGraphs 等)。对不起,我不能更具体。注意:我们的答案在解决最初提出的问题方面似乎令人满意。
我继续使用你提到的代码,然后为那个简单的数据集弹出的 Python 窗口也崩溃了。一定是我的系统问题。谢谢!【参考方案2】:
使用str.split
方法将行转换为字符串的list
。同样正如@Alien 建议的那样,您应该使用range
函数来获取x
,而不是手动枚举所有值。
y = [int(i) for i in lineDecoded.split(',')]
x = range(1,289)
import matplotlib.pyplot as plt
fig = plt.figure()
plt.plot(x, lineDecoded)
fig.show()
【讨论】:
谢谢 - 我在 Jupyter Notebook 中尝试了你的方法,但它抛出了错误matplotlib is currently using a non-GUI backend
。我尝试使用以下代码更改后端:import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt' but it throws the error 'UserWarning: This call to matplotlib.use() has no effect because the backend has already been chosen
。我是否需要放弃 Jupyter 才能让您的方法发挥作用?
根据您初始化 Jupyter Notebook 的方式,可能已经设置了 matplotlib 后端。如果是这种情况,尝试再次设置它会导致此错误。这个对话,尽管是针对 Spyder,描述了你的 Jupyter Notebook 发生了什么。 groups.google.com/forum/#!topic/spyderlib/tRwgqEAIyvs
是的,我想我无法更改 Jupyter 上的后端......我会坚持使用 PyQtGraph。谢谢【参考方案3】:
复制/粘贴您的字符串:
In [341]: astring="""137,136,151,145,141,133,145,139,140,145,144,139,143,141,139
...: ,136,137,138,137,127,142,135,136,137,134,140,127,141,134,128,139,135,1
...: 36,180,149,147,147,151,156,140,153,143,143,155,163,164,192,250,277,282
...: ...
,147,159,161,159,169,173,168,158,161,159,158,171,167,167,155,159,169,1
...: 56,159,162,157,165,161,158,147,161,171,159"""
split(',')
产生一个字符串列表。如果我将其包装在 np.array
中,我会得到一个字符串数组:
In [342]: np.array(astring.split(','))
Out[342]:
array(['137', '136', '151', '145', '141', '133', '145', '139', '140',
...
'162', '157', '165', '161', '158', '147', '161', '171', '159'],
dtype='<U3')
我需要告诉它把字符串转换成整数:
In [343]: np.array(astring.split(','),int)
Out[343]:
array([137, 136, 151, 145, 141, 133, 145, 139, 140, 145, 144, 139, 143,
141, 139, 136, 137, 138, 137, 127, 142, 135, 136, 137, 134, 140,
...., 165, 161, 158, 147, 161,
171, 159])
In [344]: _.shape
Out[344]: (288,)
我第一次尝试时,字符串以逗号结尾:"8,147,161,171,159,"
。然后拆分包含一个空字符串,np.array
无法将其转换为整数。我把它编辑了。我也可以将它从带有索引的字符串列表中删除,[:-1]
。
如果可以将字符串列表(拆分后)传递给绘图函数,那是因为该函数执行了同样的np.array(..., int)
(或浮点)转换。
[int(i) for i in astring.split(',')]
可用于创建整数列表。
【讨论】:
感谢您提供有关索引的信息。使用[:-2]
可以让我在末尾剪掉换行符和逗号。我使用您的建议将字符串转换为整数(如对@E. Ducateme 的回复中所述),但仍然无法打开一个工作 Python 窗口以显示 PyQtGraph 图而不是崩溃。
numpy
用户更有可能使用matplotlib
进行绘图而不是PyQtGraph
。您可能需要提出一个单独的 PyQtGraph
问题,重点是让该软件包正常工作。【参考方案4】:
lineDecoded = [137,136,151,145,141,133,145,139,140,145,144,139,143,141,139,136,137,138,137,127,142,135,136,137,134,140,127,141,134,128,139,135,136,180,149,147,147,151,156,140,153,143,143,155,163,164,192,250,277,282,275,258,258,248,245,231,215,225,195,195,159,186,175,168,171,173,177,185,213,224,228,231,227,219,261,229,231,231,250,253,262,276,269,274,274,277,276,272,291,303,351,417,483,500,473,399,315,263,255,239,238,244,234,231,231,242,255,272,294,293,299,314,307,306,302,310,319,304,312,327,370,464,507,514,492,425,358,327,313,299,292,291,281,259,245,232,229,224,223,222,216,226,215,211,197,202,199,197,198,193,198,185,190,196,177,198,188,183,201,193,187,159,189,184,186,185,186,185,184,196,195,200,201,198,193,241,189,186,167,179,187,174,188,180,179,169,177,173,172,175,181,175,171,180,175,176,180,184,176,190,182,172,171,179,178,174,188,175,178,167,183,171,168,174,175,171,230,175,177,159,177,170,172,171,173,168,167,169,172,168,171,177,173,167,167,171,163,170,177,172,169,167,163,157,173,161,168,174,162,165,171,165,162,152,165,173,158,193,161,161,147,159,161,159,169,173,168,158,161,159,158,171,167,167,155,159,169,156,159,162,157,165,161,158,147,161,171,159]
x = range(1,289)
import matplotlib.pyplot as plt
plt.plot(x, lineDecoded)
【讨论】:
以上是关于在 Python 3 中将逗号分隔的字符串转换为 Numpy 数组的主要内容,如果未能解决你的问题,请参考以下文章