Rumah > Artikel > pembangunan bahagian belakang > Cara menggunakan alat visualisasi Python
Meneroka Set Data
Sebelum kita meneroka memvisualisasikan data, mari kita lihat dengan pantas set data yang akan kami usahakan. Data yang akan kami gunakan datang daripada lampu terbuka. Kami akan menggunakan set data laluan, set data lapangan terbang, set data syarikat penerbangan. Antaranya, setiap baris data laluan sepadan dengan laluan penerbangan antara dua lapangan terbang;
Mula-mula kita membaca data:
# Import the pandas library. import pandas # Read in the airports data. airports = pandas.read_csv("airports.csv", header=None, dtype=str) airports.columns = ["id", "name", "city", "country", "code", "icao", "latitude", "longitude", "altitude", "offset", "dst", "timezone"] # Read in the airlines data. airlines = pandas.read_csv("airlines.csv", header=None, dtype=str) airlines.columns = ["id", "name", "alias", "iata", "icao", "callsign", "country", "active"] # Read in the routes data. routes = pandas.read_csv("routes.csv", header=None, dtype=str) routes.columns = ["airline", "airline_id", "source", "source_id", "dest", "dest_id", "codeshare", "stops", "equipment"]
Data ini tidak mempunyai item pertama lajur, jadi kami menambah item pertama lajur dengan memberikan lajur atribut . Kami ingin membaca setiap lajur sebagai rentetan kerana berbuat demikian memudahkan langkah seterusnya untuk membandingkan bingkai data yang berbeza menggunakan id baris sebagai padanan. Kami mencapai ini dengan menetapkan nilai atribut dtype apabila membaca data.
Jadi sebelum itu kita perlu melakukan beberapa kerja pembersihan data.
laluan = laluan[laluan["airline_id"] != "//N"]
Baris arahan ini memastikan kami hanya mengandungi data berangka dalam lajur airline_id.
Membuat histogram
Sekarang kita memahami struktur data, kita boleh mula memplot titik untuk terus meneroka masalah. Mula-mula, kita akan menggunakan alat matplotlib ialah perpustakaan plot peringkat rendah dalam timbunan Python, jadi ia memerlukan lebih banyak arahan daripada perpustakaan alat lain untuk membuat lengkung yang kelihatan baik. Sebaliknya, anda boleh menggunakan matplotlib untuk membuat hampir mana-mana lengkung kerana ia sangat fleksibel, dan harga fleksibiliti ialah ia sangat sukar untuk digunakan.
Kami mula-mula menunjukkan taburan panjang laluan bagi syarikat penerbangan yang berbeza dengan membuat histogram. Histogram membahagikan panjang semua laluan kepada julat nilai yang berbeza, dan kemudian mengira laluan yang termasuk dalam julat nilai yang berbeza. Daripada ini kita dapat mengetahui syarikat penerbangan yang mempunyai laluan panjang dan syarikat penerbangan yang mempunyai laluan pendek.
Untuk mencapai ini, kita perlu terlebih dahulu mengira panjang laluan Langkah pertama ialah menggunakan formula jarak Kita akan menggunakan formula jarak semisin kosinus untuk mengira jarak antara dua titik yang digambarkan oleh longitud dan jarak latitud.
import math def haversine(lon1, lat1, lon2, lat2): # Convert coordinates to floats. lon1, lat1, lon2, lat2 = [float(lon1), float(lat1), float(lon2), float(lat2)] # Convert to radians from degrees. lon1, lat1, lon2, lat2 = map(math.radians, [lon1, lat1, lon2, lat2]) # Compute distance. dlon = lon2 - lon1 dlat = lat2 - lat1 a = math.sin(dlat/2)**2 + math.cos(lat1) * math.cos(lat2) * math.sin(dlon/2)**2 c = 2 * math.asin(math.sqrt(a)) km = 6367 * c return km
Kami kemudiannya boleh menggunakan fungsi untuk mengira jarak sehala antara lapangan terbang asal dan destinasi. Kita perlu mendapatkan source_id dan dest_id yang sepadan dengan bingkai data lapangan terbang daripada bingkai data laluan, dan kemudian memadankannya dengan lajur id set data lapangan terbang Kemudian kita hanya perlu mengira Fungsi ini adalah seperti ini:
def calc_dist(row): dist = 0 try: # Match source and destination to get coordinates. source = airports[airports["id"] == row["source_id"]].iloc[0] dest = airports[airports["id"] == row["dest_id"]].iloc[0] # Use coordinates to compute distance. dist = haversine(dest["longitude"], dest["latitude"], source["longitude"], source["latitude"]) except (ValueError, IndexError): pass return dist
Jika Jika lajur source_id dan dest_id tidak mempunyai nilai yang sah, maka fungsi ini akan melaporkan ralat. Oleh itu, kita perlu menambah modul cuba/tangkap untuk menangkap situasi tidak sah ini.
***, kami akan menggunakan panda untuk menggunakan fungsi pengiraan jarak pada bingkai data laluan. Ini akan memberi kita urutan panda yang mengandungi semua panjang laluan dalam kilometer.
route_lengths = routes.apply(calc_dist, axis=1)
Sekarang kita mempunyai urutan jarak laluan, kita akan mencipta histogram yang akan mengkategorikan data kepada julat yang sepadan, dan kemudian hitung berapa banyak laluan yang termasuk dalam setiap julat berbeza:
import matplotlib.pyplot as plt %matplotlib inline plt.hist(route_lengths, bins=20)
Kami menggunakan import matplotlib.pyplot sebagai plt untuk mengimport fungsi plot matplotlib. Kemudian kami menggunakan %matplotlib sebaris untuk menetapkan matplotlib untuk menarik mata dalam buku nota ipython Akhirnya, kami menggunakan plt.hist(route_lengths, bins=20) untuk mendapatkan histogram. Seperti yang telah kita lihat, syarikat penerbangan cenderung untuk mengendalikan laluan jarak dekat yang berdekatan dan bukannya laluan jarak jauh yang jauh.
Menggunakan seaborn
Kita boleh menggunakan seaborn untuk melakukan pengesanan titik yang serupa ialah perpustakaan peringkat tinggi untuk Python. Seaborn dibina berdasarkan matplotlib dan melakukan beberapa jenis plot, yang selalunya berkaitan dengan kerja statistik mudah. Kita boleh menggunakan fungsi distplot untuk memplot histogram berdasarkan jangkaan kepadatan kebarangkalian teras. Jangkaan ketumpatan teras ialah lengkung - pada asasnya lengkung yang lebih licin daripada histogram dan lebih mudah untuk melihat peraturan.
import seaborn seaborn.distplot(route_lengths, bins=20)
seaborn juga mempunyai gaya lalai yang lebih cantik. seaborn tidak mengandungi versi yang sepadan dengan setiap versi matplotlib, tetapi ia sememangnya alat lukisan titik cepat yang baik, dan berbanding dengan carta lalai matplotlib, ia boleh membantu kami memahami maksud di sebalik data dengan lebih baik. Jika anda ingin melakukan kerja statistik yang lebih mendalam, seaborn juga merupakan perpustakaan yang bagus.
Carta palang
柱状图也虽然很好,但是有时候我们会需要航空公司的平均路线长度。这时候我们可以使用条形图--每条航线都会有一个单独的状态条,显示航空公司航线 的平均长度。从中我们可以看出哪家是国内航空公司哪家是国际航空公司。我们可以使用pandas,一个python的数据分析库,来酸楚每个航空公司的平 均航线长度。
import numpy # Put relevant columns into a dataframe. route_length_df = pandas.DataFrame({"length": route_lengths, "id": routes["airline_id"]}) # Compute the mean route length per airline. airline_route_lengths = route_length_df.groupby("id").aggregate(numpy.mean) # Sort by length so we can make a better chart. airline_route_lengths = airline_route_lengths.sort("length", ascending=False)
我们首先用航线长度和航空公司的id来搭建一个新的数据框架。我们基于airline_id把route_length_df拆分成组,为每个航空 公司建立一个大体的数据框架。然后我们调用pandas的aggregate函数来获取航空公司数据框架中长度列的均值,然后把每个获取到的值重组到一个 新的数据模型里。之后把数据模型进行排序,这样就使得拥有最多航线的航空公司拍到了前面。
这样就可以使用matplotlib把结果画出来。
plt.bar(range(airline_route_lengths.shape[0]), airline_route_lengths["length"])
Matplotlib的plt.bar方法根据每个数据模型的航空公司平均航线长度(airline_route_lengths["length"])来做图。
问题是我们想看出哪家航空公司拥有的航线长度是什么并不容易。为了解决这个问题,我们需要能够看到坐标轴标签。这有点难,毕竟有这么多的航空公司。 一个能使问题变得简单的方法是使图表具有交互性,这样能实现放大跟缩小来查看轴标签。我们可以使用bokeh库来实现这个--它能便捷的实现交互性,作出 可缩放的图表。
要使用booked,我们需要先对数据进行预处理:
def lookup_name(row): try: # Match the row id to the id in the airlines dataframe so we can get the name. name = airlines["name"][airlines["id"] == row["id"]].iloc[0] except (ValueError, IndexError): name = "" return name # Add the index (the airline ids) as a column. airline_route_lengths["id"] = airline_route_lengths.index.copy() # Find all the airline names. airline_route_lengths["name"] = airline_route_lengths.apply(lookup_name, axis=1) # Remove duplicate values in the index. airline_route_lengths.index = range(airline_route_lengths.shape[0])
上面的代码会获取airline_route_lengths中每列的名字,然后添加到name列上,这里存贮着每个航空公司的名字。我们也添加到id列上以实现查找(apply函数不传index)。
***,我们重置索引序列以得到所有的特殊值。没有这一步,Bokeh 无法正常运行。
现在,我们可以继续说图表问题:
import numpy as np from bokeh.io import output_notebook from bokeh.charts import Bar, show output_notebook() p = Bar(airline_route_lengths, 'name', values='length', title="Average airline route lengths") show(p)
用 output_notebook 创建背景虚化,在 iPython 的 notebook 里画出图。然后,使用数据帧和特定序列制作条形图。***,显示功能会显示出该图。
这个图实际上不是一个图像--它是一个 JavaScript 插件。因此,我们在下面展示的是一幅屏幕截图,而不是真实的表格。
有了它,我们可以放大,看哪一趟航班的飞行路线最长。上面的图像让这些表格看起来挤在了一起,但放大以后,看起来就方便多了。
水平条形图
Pygal 是一个能快速制作出有吸引力表格的数据分析库。我们可以用它来按长度分解路由。首先把我们的路由分成短、中、长三个距离,并在 route_lengths 里计算出它们各占的百分比。
long_routes = len([k for k in route_lengths if k > 10000]) / len(route_lengths) medium_routes = len([k for k in route_lengths if k < 10000 and k > 2000]) / len(route_lengths) short_routes = len([k for k in route_lengths if k < 2000]) / len(route_lengths)
然后我们可以在 Pygal 的水平条形图里把每一个都绘成条形图:
import pygal from IPython.display import SVG chart = pygal.HorizontalBar() chart.title = 'Long, medium, and short routes' chart.add('Long', long_routes * 100) chart.add('Medium', medium_routes * 100) chart.add('Short', short_routes * 100) chart.render_to_file('routes.svg') SVG(filename='routes.svg')
首先,我们使用 pandasapplymethod 计算每个名称的长度。它将找到每个航空公司的名字字符的数量。然后,我们使用 matplotlib 做一个散点图来比较航空 id 的长度。当我们绘制时,我们把 theidcolumn of airlines 转换为整数类型。如果我们不这样做是行不通的,因为它需要在 x 轴上的数值。我们可以看到不少的长名字都出现在早先的 id 中。这可能意味着航空公司在成立前往往有较长的名字。
我们可以使用 seaborn 验证这个直觉。Seaborn 增强版的散点图,一个联合的点,它显示了两个变量是相关的,并有着类似地分布。
data = pandas.DataFrame({"lengths": name_lengths, "ids": airlines["id"].astype(int)})
seaborn.jointplot(x="ids", y="lengths", data=data)
画弧线
在地图上看到所有的航空路线是很酷的,幸运的是,我们可以使用 basemap 来做这件事。我们将画弧线连接所有的机场出发地和目的地。每个弧线想展示一个段都航线的路径。不幸的是,展示所有的线路又有太多的路由,这将会是一团糟。 替代,我们只现实前 3000 个路由。
# Make a base map with a mercator projection. Draw the coastlines. m = Basemap(projection='merc',llcrnrlat=-80,urcrnrlat=80,llcrnrlon=-180,urcrnrlon=180,lat_ts=20,resolution='c') m.drawcoastlines() # Iterate through the first 3000 rows. for name, row in routes[:3000].iterrows(): try: # Get the source and dest airports. source = airports[airports["id"] == row["source_id"]].iloc[0] dest = airports[airports["id"] == row["dest_id"]].iloc[0] # Don't draw overly long routes. if abs(float(source["longitude"]) - float(dest["longitude"])) < 90: # Draw a great circle between source and dest airports. m.drawgreatcircle(float(source["longitude"]), float(source["latitude"]), float(dest["longitude"]), float(dest["latitude"]),linewidth=1,color='b') except (ValueError, IndexError): pass # Show the map. plt.show()
我们将做的最终的探索是画一个机场网络图。每个机场将会是网络中的一个节点,并且如果两点之间有路由将划出节点之间的连线。如果有多重路由,将添加线的权重,以显示机场连接的更多。将使用 networkx 库来做这个功能。
首先,计算机场之间连线的权重。
# Initialize the weights dictionary. weights = {} # Keep track of keys that have been added once -- we only want edges with a weight of more than 1 to keep our network size manageable. added_keys = [] # Iterate through each route. for name, row in routes.iterrows(): # Extract the source and dest airport ids. source = row["source_id"] dest = row["dest_id"] # Create a key for the weights dictionary. # This corresponds to one edge, and has the start and end of the route. key = "{0}_{1}".format(source, dest) # If the key is already in weights, increment the weight. if key in weights: weights[key] += 1 # If the key is in added keys, initialize the key in the weights dictionary, with a weight of 2. elif key in added_keys: weights[key] = 2 # If the key isn't in added_keys yet, append it. # This ensures that we aren't adding edges with a weight of 1. else: added_keys.append(key)
一旦上面的代码运行,这个权重字典就包含了每两个机场之间权重大于或等于 2 的连线。所以任何机场有两个或者更多连接的路由将会显示出来。
# Import networkx and initialize the graph. import networkx as nx graph = nx.Graph() # Keep track of added nodes in this set so we don't add twice. nodes = set() # Iterate through each edge. for k, weight in weights.items(): try: # Split the source and dest ids and convert to integers. source, dest = k.split("_") source, dest = [int(source), int(dest)] # Add the source if it isn't in the nodes. if source not in nodes: graph.add_node(source) # Add the dest if it isn't in the nodes. if dest not in nodes: graph.add_node(dest) # Add both source and dest to the nodes set. # Sets don't allow duplicates. nodes.add(source) nodes.add(dest) # Add the edge to the graph. graph.add_edge(source, dest, weight=weight) except (ValueError, IndexError): pass pos=nx.spring_layout(graph) # Draw the nodes and edges. nx.draw_networkx_nodes(graph,pos, node_color='red', node_size=10, alpha=0.8) nx.draw_networkx_edges(graph,pos,width=1.0,alpha=1) # Show the plot. plt.show()
Atas ialah kandungan terperinci Cara menggunakan alat visualisasi Python. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!