使用字典中的数据创建 3D 曲面图
Creating 3D surface plot using data from dictionaries
我无法弄清楚如何使用 python 中的 matplotlib 将我的数据转换为曲面图的 X、Y 和 Z 轴。数据来自一个包含 5 个字母单词列表的文件,我的程序运行该文件并计算每个字母在单词的每个位置出现的次数。它存储在 5 个不同的字典中,每个字典对应一个位置。我在想我将不得不使用 .keys() 和 .values() 方法,但我并不肯定。
我进入 excel 并制作图表以显示我正在尝试做的事情的示例。
这是我目前的代码:
import string
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
import numpy as np
#Creates a list of the alphabet in uppercase
alphabet = string.ascii_uppercase
letter_list = list(alphabet)
#Creates dictionary for lettercount. Keys = A-Z, Values = 0
lettercount = {i: 0 for i in letter_list}
#Creates dictonaries for position frequency. Keys = A-Z, Values = 0
position1_freq = {i: 0 for i in letter_list}
position2_freq = {i: 0 for i in letter_list}
position3_freq = {i: 0 for i in letter_list}
position4_freq = {i: 0 for i in letter_list}
position5_freq = {i: 0 for i in letter_list}
with open("answers.txt") as f:
for i in f:
i = i.rstrip()
for word in i.split(" "):
for letter in range(len(word)):
#Iterates through alphabet
for j in letter_list:
#If the letter in the word = j it will add 1 to lettercount and depending on what value the indicie letter is, 1 will be added to the proper position frequency
if word[letter] == j:
lettercount[j] += 1
if letter == 0:
position1_freq[j] += 1
if letter == 1:
position2_freq[j] += 1
if letter == 2:
position3_freq[j] += 1
if letter == 3:
position4_freq[j] += 1
if letter == 4:
position5_freq[j] += 1
#Sorts the lettercount dictionary to be high to low
sort_lettercount = sorted(lettercount.items(), key = lambda x: x[1], reverse= True)
fig = plt.figure()
ax = plt.axes(projection = '3d')
plt.show()
这是一个完整的例子。我使用了列表和字典理解,因为它们在 python 中很常见(很好习惯!)和标准库中的 Counter
class。因此,如果您不习惯,代码可能会有点难以阅读,但这种风格在 python 中很常见,所以我建议学习它而不是使用明确的 for-loops。 Counter
对象是一种字典,因此可以将其视为字典。 :)
我再用.values()
。 Counter 上的函数来提取结果。我将它放入一个 numpy 数组中,因为这是 matplotlib 所需要的。
最后,在 matplotlib 中创建 3d 图有点做作。 Matplotlib 不太适合分类数据(例如在 X 轴上有字母),也不太适合带有水平色带的 3d 图(如您的 excel 示例)。
总之,就在这里:
from string import ascii_uppercase
from collections import Counter
# a dictionary with all ascii lettters as keys, and only zeros as values
zero_counts = {c:0 for c in ascii_uppercase}
with open('answers.txt') as f:
# read the file into a list, remove trailing newlines and make sure all is uppercase
lines = [line.strip().upper() for line in f.readlines()]
# transpose the list, so that instead of having N 5-letter words, we now have 5 N-letter words
list_of_chars_per_pos = zip(*lines)
# for each of these 5 "words", count the number of occurrances of each letter
# then add these occurences into a copy of the "zero" dictionary from before
# so now we have 5 dictionaries holding the count for letter 0,1,2,3 and 4
char_counts_per_pos = [zero_counts | Counter(chars) for chars in list_of_chars_per_pos]
# matplotlib only works with numpy data structures, so lets change into that!
import numpy as np
x = np.arange(len(ascii_uppercase)) # the x axis will correspond to the letters
y = np.arange(5) # the y axis will be the positions
X,Y = np.meshgrid(x,y) # create 2D arrays with the X and Y coordinates
# here we extract the data from the dictionaries using the .values() method
Z = np.array([list(dictionary.values()) for dictionary in char_counts_per_pos])
# now create the plot! create 3d axes on a new figure and draw the plot
# there is quite a bit of customization that can be done to the plot to make it look
# in whatever way you like.
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator, FixedLocator
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
surf= ax.plot_surface(X=X,Y=Y,Z=Z)
ax.xaxis.set_major_locator(FixedLocator(x))
ax.set_xticklabels(ascii_uppercase)
ax.set_box_aspect((26,5,5))
ax.zaxis.set_major_locator(MaxNLocator(integer=True))
ax.set_zlabel("Counts")
ax.set_ylabel("Position")
# finally, show the plot. :)
plt.show()
通过运行把它放在下面的文本文件中answers.txt
abbot
mince
grate
dodos
piggy
baron
party
我明白了
我无法弄清楚如何使用 python 中的 matplotlib 将我的数据转换为曲面图的 X、Y 和 Z 轴。数据来自一个包含 5 个字母单词列表的文件,我的程序运行该文件并计算每个字母在单词的每个位置出现的次数。它存储在 5 个不同的字典中,每个字典对应一个位置。我在想我将不得不使用 .keys() 和 .values() 方法,但我并不肯定。
我进入 excel 并制作图表以显示我正在尝试做的事情的示例。
这是我目前的代码:
import string
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
import numpy as np
#Creates a list of the alphabet in uppercase
alphabet = string.ascii_uppercase
letter_list = list(alphabet)
#Creates dictionary for lettercount. Keys = A-Z, Values = 0
lettercount = {i: 0 for i in letter_list}
#Creates dictonaries for position frequency. Keys = A-Z, Values = 0
position1_freq = {i: 0 for i in letter_list}
position2_freq = {i: 0 for i in letter_list}
position3_freq = {i: 0 for i in letter_list}
position4_freq = {i: 0 for i in letter_list}
position5_freq = {i: 0 for i in letter_list}
with open("answers.txt") as f:
for i in f:
i = i.rstrip()
for word in i.split(" "):
for letter in range(len(word)):
#Iterates through alphabet
for j in letter_list:
#If the letter in the word = j it will add 1 to lettercount and depending on what value the indicie letter is, 1 will be added to the proper position frequency
if word[letter] == j:
lettercount[j] += 1
if letter == 0:
position1_freq[j] += 1
if letter == 1:
position2_freq[j] += 1
if letter == 2:
position3_freq[j] += 1
if letter == 3:
position4_freq[j] += 1
if letter == 4:
position5_freq[j] += 1
#Sorts the lettercount dictionary to be high to low
sort_lettercount = sorted(lettercount.items(), key = lambda x: x[1], reverse= True)
fig = plt.figure()
ax = plt.axes(projection = '3d')
plt.show()
这是一个完整的例子。我使用了列表和字典理解,因为它们在 python 中很常见(很好习惯!)和标准库中的 Counter
class。因此,如果您不习惯,代码可能会有点难以阅读,但这种风格在 python 中很常见,所以我建议学习它而不是使用明确的 for-loops。 Counter
对象是一种字典,因此可以将其视为字典。 :)
我再用.values()
。 Counter 上的函数来提取结果。我将它放入一个 numpy 数组中,因为这是 matplotlib 所需要的。
最后,在 matplotlib 中创建 3d 图有点做作。 Matplotlib 不太适合分类数据(例如在 X 轴上有字母),也不太适合带有水平色带的 3d 图(如您的 excel 示例)。
总之,就在这里:
from string import ascii_uppercase
from collections import Counter
# a dictionary with all ascii lettters as keys, and only zeros as values
zero_counts = {c:0 for c in ascii_uppercase}
with open('answers.txt') as f:
# read the file into a list, remove trailing newlines and make sure all is uppercase
lines = [line.strip().upper() for line in f.readlines()]
# transpose the list, so that instead of having N 5-letter words, we now have 5 N-letter words
list_of_chars_per_pos = zip(*lines)
# for each of these 5 "words", count the number of occurrances of each letter
# then add these occurences into a copy of the "zero" dictionary from before
# so now we have 5 dictionaries holding the count for letter 0,1,2,3 and 4
char_counts_per_pos = [zero_counts | Counter(chars) for chars in list_of_chars_per_pos]
# matplotlib only works with numpy data structures, so lets change into that!
import numpy as np
x = np.arange(len(ascii_uppercase)) # the x axis will correspond to the letters
y = np.arange(5) # the y axis will be the positions
X,Y = np.meshgrid(x,y) # create 2D arrays with the X and Y coordinates
# here we extract the data from the dictionaries using the .values() method
Z = np.array([list(dictionary.values()) for dictionary in char_counts_per_pos])
# now create the plot! create 3d axes on a new figure and draw the plot
# there is quite a bit of customization that can be done to the plot to make it look
# in whatever way you like.
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator, FixedLocator
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
surf= ax.plot_surface(X=X,Y=Y,Z=Z)
ax.xaxis.set_major_locator(FixedLocator(x))
ax.set_xticklabels(ascii_uppercase)
ax.set_box_aspect((26,5,5))
ax.zaxis.set_major_locator(MaxNLocator(integer=True))
ax.set_zlabel("Counts")
ax.set_ylabel("Position")
# finally, show the plot. :)
plt.show()
通过运行把它放在下面的文本文件中answers.txt
abbot
mince
grate
dodos
piggy
baron
party
我明白了