查看原文
其他

UFO长啥样?

LEMON Python数据之道 2022-04-24

前言

真心讲,长这么大,还没有见过UFO长啥样,偶然看到美国UFO报告中心有关于UFO时间记录的详细信息,突然想分析下这些记录里都包含了那些有趣的信息,于是有了这次的分析过程。

当然,原始数据包含的记录信息比较多,我只是进了了比较简单的分析,有兴趣的童鞋可以一起来分析,别忘了也给大家分享下您的分析情况哦。

本次分析的主要内容涉及以下几个方面:

  • UFO长啥样?

  • UFO在哪些地方出现的次数较多?

  • UFO在哪些年份出现的次数较多?

  • 热力图同时显示哪些州和哪些年UFO出现次数最多

  1. import pandas as pd

  2. import numpy as np

  3. import matplotlib.pyplot as plt

  4. % matplotlib inline

  5. plt.style.use('ggplot')

1 数据整理与清洗

  1. df =  pd.read_csv('nuforc_events.csv')

  1. print(df.shape) # 查看数据的结构

  2. print(df.head())

  1. (110265, 13)

  2.             Event_Time  Event_Date    Year  Month   Day  Hour  Minute  \

  3. 0  2017-04-20T14:15:00Z  2017-04-20  2017.0    4.0  20.0  14.0    15.0  

  4. 1  2017-04-20T04:56:00Z  2017-04-20  2017.0    4.0  20.0   4.0    56.0  

  5. 2  2017-04-19T23:55:00Z  2017-04-19  2017.0    4.0  19.0  23.0    55.0  

  6. 3  2017-04-19T23:50:00Z  2017-04-19  2017.0    4.0  19.0  23.0    50.0  

  7. 4  2017-04-19T23:29:00Z  2017-04-19  2017.0    4.0  19.0  23.0    29.0  

  8.         City State     Shape     Duration  \

  9. 0     Palmyra    NJ     Other    5 minutes  

  10. 1  Bridgeview    IL     Light   20 seconds  

  11. 2      Newton    AL  Triangle    5 seconds  

  12. 3      Newton    AL  Triangle  5-6 minutes  

  13. 4      Denver    CO     Light       1 hour  

  14.                                             Summary  \

  15. 0    I observed an aircraft that seemed to look odd.  

  16. 1  Bridgeview, IL, blue light.  ((anonymous report))  

  17. 2                               Silent triangle UFO.  

  18. 3  My friend and I stepped outside hoping to catc...  

  19. 4  Moved slow but made quick turns staying and ci...  

  20.                                           Event_URL  

  21. 0  http://www.nuforc.org/webreports/133/S133726.html  

  22. 1  http://www.nuforc.org/webreports/133/S133720.html  

  23. 2  http://www.nuforc.org/webreports/133/S133724.html  

  24. 3  http://www.nuforc.org/webreports/133/S133723.html  

  25. 4  http://www.nuforc.org/webreports/133/S133721.html  

  • 由于存在许多包含NaN的数据信息,在进行分析之前,先用dropna()方法去除包含NaN的行数

  1. df_clean = df.dropna()

  2. print(df_clean.shape) # 查看去除Nan后还有多少行

  3. print(df_clean.head())

  1. (95004, 13)

  2.             Event_Time  Event_Date    Year  Month   Day  Hour  Minute  \

  3. 0  2017-04-20T14:15:00Z  2017-04-20  2017.0    4.0  20.0  14.0    15.0  

  4. 1  2017-04-20T04:56:00Z  2017-04-20  2017.0    4.0  20.0   4.0    56.0  

  5. 2  2017-04-19T23:55:00Z  2017-04-19  2017.0    4.0  19.0  23.0    55.0  

  6. 3  2017-04-19T23:50:00Z  2017-04-19  2017.0    4.0  19.0  23.0    50.0  

  7. 4  2017-04-19T23:29:00Z  2017-04-19  2017.0    4.0  19.0  23.0    29.0  

  8.         City State     Shape     Duration  \

  9. 0     Palmyra    NJ     Other    5 minutes  

  10. 1  Bridgeview    IL     Light   20 seconds  

  11. 2      Newton    AL  Triangle    5 seconds  

  12. 3      Newton    AL  Triangle  5-6 minutes  

  13. 4      Denver    CO     Light       1 hour  

  14.                                             Summary  \

  15. 0    I observed an aircraft that seemed to look odd.  

  16. 1  Bridgeview, IL, blue light.  ((anonymous report))  

  17. 2                               Silent triangle UFO.  

  18. 3  My friend and I stepped outside hoping to catc...  

  19. 4  Moved slow but made quick turns staying and ci...  

  20.                                           Event_URL  

  21. 0  http://www.nuforc.org/webreports/133/S133726.html  

  22. 1  http://www.nuforc.org/webreports/133/S133720.html  

  23. 2  http://www.nuforc.org/webreports/133/S133724.html  

  24. 3  http://www.nuforc.org/webreports/133/S133723.html  

  25. 4  http://www.nuforc.org/webreports/133/S133721.html  

  • 由于1900年以前的数据较少,这里选择1900年以后的数据来进行分析,如下:

  1. df_clean = df_clean[df_clean['Year']>=1900] # 获取1900年以后的数据来进行分析

  • 查看导入的每列数据的数据类型,通过运行结果,可以看到,“Event_Date”列并不是日期类型,因此要将之转换。

  • 可以采用pd.to_datetime()方法来操作

  1. df_clean.dtypes

  1. Event_Time     object

  2. Event_Date     object

  3. Year          float64

  4. Month         float64

  5. Day           float64

  6. Hour          float64

  7. Minute        float64

  8. City           object

  9. State          object

  10. Shape          object

  11. Duration       object

  12. Summary        object

  13. Event_URL      object

  14. dtype: object

  • 用pd.to_datetime()方法来将str格式的日期转换成日期类型

  1. pd.to_datetime(df_clean['Event_Date']) # 1061-12-31年不能显示

  2. # OutOfBoundsDatetime: Out of bounds nanosecond timestamp: 1061-12-31 00:00:00

  3. df_clean.dtypes

  1. Event_Time     object

  2. Event_Date     object

  3. Year          float64

  4. Month         float64

  5. Day           float64

  6. Hour          float64

  7. Minute        float64

  8. City           object

  9. State          object

  10. Shape          object

  11. Duration       object

  12. Summary        object

  13. Event_URL      object

  14. dtype: object

2 UFO长啥样?

  • 按UFO出现的形状类型来分析,统计不同类型的UFO出现的次数

  1. s_shape = df_clean.groupby('Shape')['Event_Date'].count()

  2. print(type(s_shape))

  3. s_shape.sort_values(inplace=True)

  4. s_shape

  1. <class 'pandas.core.series.Series'>

  2. Shape

  3. Changed          1

  4. Hexagon          1

  5. Pyramid          1

  6. Flare            1

  7. Round            2

  8. Crescent         2

  9. Delta            7

  10. Cross          287

  11. Cone           383

  12. Egg            842

  13. Teardrop       866

  14. Chevron       1187

  15. Diamond       1405

  16. Cylinder      1495

  17. Rectangle     1620

  18. Flash         1717

  19. Cigar         2313

  20. Changing      2378

  21. Formation     3070

  22. Oval          4332

  23. Disk          5841

  24. Sphere        6482

  25. Other         6658

  26. Unknown       6887

  27. Fireball      7785

  28. Triangle      9358

  29. Circle        9818

  30. Light        20254

  31. Name: Event_Date, dtype: int64

剔除特殊情况

  • 剔除出现次数少于10次的类型

  • 剔除“Unknown”及“Other”类型

  1. s_shape_normal = s_shape[s_shape.values>10]

  2. s_shape_normal

  1. Shape

  2. Cross          287

  3. Cone           383

  4. Egg            842

  5. Teardrop       866

  6. Chevron       1187

  7. Diamond       1405

  8. Cylinder      1495

  9. Rectangle     1620

  10. Flash         1717

  11. Cigar         2313

  12. Changing      2378

  13. Formation     3070

  14. Oval          4332

  15. Disk          5841

  16. Sphere        6482

  17. Other         6658

  18. Unknown       6887

  19. Fireball      7785

  20. Triangle      9358

  21. Circle        9818

  22. Light        20254

  23. Name: Event_Date, dtype: int64

  1. s_shape_normal = s_shape_normal[s_shape_normal.index.isin(['Unknown', 'Other'])==False]

  2. s_shape_normal

  1. Shape

  2. Cross          287

  3. Cone           383

  4. Egg            842

  5. Teardrop       866

  6. Chevron       1187

  7. Diamond       1405

  8. Cylinder      1495

  9. Rectangle     1620

  10. Flash         1717

  11. Cigar         2313

  12. Changing      2378

  13. Formation     3070

  14. Oval          4332

  15. Disk          5841

  16. Sphere        6482

  17. Fireball      7785

  18. Triangle      9358

  19. Circle        9818

  20. Light        20254

  21. Name: Event_Date, dtype: int64

  1. from matplotlib import font_manager as fm

  2. from  matplotlib import cm

  3. labels = s_shape_normal.index

  4. sizes = s_shape_normal.values

  5. explode = (0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1)  # "explode" , show the selected slice

  6. fig, axes = plt.subplots(figsize=(10,5),ncols=2) # 设置绘图区域大小

  7. ax1, ax2 = axes.ravel()

  8. colors = cm.rainbow(np.arange(len(sizes))/len(sizes)) # colormaps: Paired, autumn, rainbow, gray,spring,Darks

  9. patches, texts, autotexts = ax1.pie(sizes, labels=labels, autopct='%1.0f%%',explode=explode,

  10.        shadow=False, startangle=150, colors=colors, labeldistance=1.2,pctdistance=1.05, radius=0.95)

  11. # labeldistance: 控制labels显示的位置

  12. # pctdistance: 控制百分比显示的位置

  13. # radius: 控制切片突出的距离

  14. ax1.axis('equal')  

  15. # 重新设置字体大小

  16. proptease = fm.FontProperties()

  17. proptease.set_size('xx-small')

  18. # font size include: ‘xx-small’,x-small’,'small’,'medium’,‘large’,‘x-large’,‘xx-large’ or number, e.g. '12'

  19. plt.setp(autotexts, fontproperties=proptease)

  20. plt.setp(texts, fontproperties=proptease)

  21. ax1.set_title('Shapes', loc='center')

  22. # ax2 只显示图例(legend)

  23. ax2.axis('off')

  24. ax2.legend(patches, labels, loc='center left', fontsize=9)

  25. # plt.tight_layout()

  26. # plt.savefig("pie_shape_ufo.png", bbox_inches='tight')

  27. plt.savefig('ufo_shapes.jpg')

  28. plt.show()

运行结果如下:

3 UFO在美国那些州(state)出现的次数比较多?

按"State"进行分组运算,统计ufo在各个州出现的次数

  1. s_state = df_clean.groupby('State')['Event_Date'].count()

  2. print(type(s_state))

  3. s_state.head()

  1. <class 'pandas.core.series.Series'>

  2. State

  3. AB     438

  4. AK     472

  5. AL     930

  6. AR     791

  7. AZ    3488

  8. Name: Event_Date, dtype: int64

将分析得到的结果进行可视化显示,如下:

  1. fig, ax1 = plt.subplots(figsize=(12,8))

  2. width = 0.5

  3. state = s_state.index

  4. x_pos1 = np.arange(len(state))

  5. y1 = s_state.values

  6. ax1.bar(x_pos1, y1,color='#4F81BD',align='center', width=width, label='Amounts', linewidth=0)

  7. ax1.set_title('Amount of reporting UFO events by State ')

  8. ax1.set_xlim(-1, len(state))

  9. ax1.set_xticks(x_pos1)

  10. ax1.set_xticklabels(state, rotation = -90)

  11. ax1.set_ylabel('Amount')

  12. fig.savefig('ufo_state.jpg')

  13. plt.show()

运行结果如下:

从上图可看出,ufo在加州(CA)出现的总次数明显比其他地方多,难道是ufo偏爱加州人民?

4 UFO在哪些年份出现的次数较多?

按"Year"进行分组运算,统计ufo在各个年份出现的次数

  1. # df_clean['Year'].astype(int)

  2. s_year = df_clean.groupby(df_clean['Year'].astype(int))['Event_Date'].count()

  3. print(type(s_year))

  4. s_year.head()

  1. <class 'pandas.core.series.Series'>

  2. Year

  3. 1905    1

  4. 1910    2

  5. 1920    1

  6. 1925    1

  7. 1929    1

  8. Name: Event_Date, dtype: int64

将分析得到的结果进行可视化显示,如下:

  1. fig, ax = plt.subplots(figsize=(12,20))

  2. # fig, ax1 = plt.subplots(figsize=(12,8))

  3. # fig, axes = plt.subplots(nrows=2, figsize=(12,8))

  4. # fig, axes = plt.subplots(ncols=2, figsize=(18,4))

  5. year = s_year.index

  6. y_pos = np.arange(len(year))

  7. x_value = s_year.values

  8. ax.barh(y_pos, x_value,color='#4F81BD',align='center', label='Amounts', linewidth=0)

  9. ax.set_title('Amount of reporting UFO events by Year ')

  10. ax.set_ylim(-0.5, len(year)-0.5)

  11. ax.set_yticks(y_pos)

  12. ax.set_yticklabels(year, rotation = 0, fontsize=6)

  13. ax.set_xlabel('Amount')

  14. plt.savefig('ufo_year.jpg')

  15. plt.show()

运行结果如下:

从上图可看出,近年来UFO出现的报告次数最多

5 1997年以后的UFO事件分析

  • 通过上述分析可看出,1997年以前,报告发现UFO的事件相对较少,下面将针对1997年以后的情况进行分析

  1. df_97 = df_clean[(df_clean['Year']>=1997)]

  2. df_97['Year'] = df_97['Year'].astype(int)

  3. # df_97.astype({'Year':int})

  4. print(df_97.shape)

  5. print(df_97.head())

  1. (86041, 13)

  2.             Event_Time  Event_Date  Year  Month   Day  Hour  Minute  \

  3. 0  2017-04-20T14:15:00Z  2017-04-20  2017    4.0  20.0  14.0    15.0  

  4. 1  2017-04-20T04:56:00Z  2017-04-20  2017    4.0  20.0   4.0    56.0  

  5. 2  2017-04-19T23:55:00Z  2017-04-19  2017    4.0  19.0  23.0    55.0  

  6. 3  2017-04-19T23:50:00Z  2017-04-19  2017    4.0  19.0  23.0    50.0  

  7. 4  2017-04-19T23:29:00Z  2017-04-19  2017    4.0  19.0  23.0    29.0  

  8.         City State     Shape     Duration  \

  9. 0     Palmyra    NJ     Other    5 minutes  

  10. 1  Bridgeview    IL     Light   20 seconds  

  11. 2      Newton    AL  Triangle    5 seconds  

  12. 3      Newton    AL  Triangle  5-6 minutes  

  13. 4      Denver    CO     Light       1 hour  

  14.                                             Summary  \

  15. 0    I observed an aircraft that seemed to look odd.  

  16. 1  Bridgeview, IL, blue light.  ((anonymous report))  

  17. 2                               Silent triangle UFO.  

  18. 3  My friend and I stepped outside hoping to catc...  

  19. 4  Moved slow but made quick turns staying and ci...  

  20.                                           Event_URL  

  21. 0  http://www.nuforc.org/webreports/133/S133726.html  

  22. 1  http://www.nuforc.org/webreports/133/S133720.html  

  23. 2  http://www.nuforc.org/webreports/133/S133724.html  

  24. 3  http://www.nuforc.org/webreports/133/S133723.html  

  25. 4  http://www.nuforc.org/webreports/133/S133721.html  

将数据按"Year"和"State"进行分组运算,如下:

  1. df_amount_year = df_97.groupby(['Year', 'State'])['Event_Date'].size().reset_index()

  2. df_amount_year.columns = ['Year', 'State', 'Amount']

  3. print(df_amount_year.head())

  1.   Year State  Amount

  2. 0  1997    AB       6

  3. 1  1997    AK       5

  4. 2  1997    AL       8

  5. 3  1997    AR      10

  6. 4  1997    AZ     127

  1. import seaborn as sns

  2. df_pivot = df_amount_year.pivot_table(index='State', columns='Year', values='Amount')

  3. f, ax = plt.subplots(figsize = (10, 15))

  4. cmap = sns.cubehelix_palette(start = 1, rot = 3, gamma=0.8, as_cmap = True)

  5. sns.heatmap(df_pivot, cmap = cmap, linewidths = 0.05, ax = ax)

  6. ax.set_title('Amounts per State and Year since Year 1997')

  7. ax.set_xlabel('Year')

  8. ax.set_ylabel('State')

  9. ax.set_xticklabels(ax.get_xticklabels(), rotation=90)

  10. f.savefig('ufo_per_year_state.jpg')


  • 上图中,颜色越深的地方,表示UFO事件报告的次数越多。


原始数据来源于美国的UFO事件报告中心


更多精彩内容请关注公众号:

“Python数据之道”


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存