探索性数据分析:伦敦交通的失物招领物品

原文:towardsdatascience.com/exploratory-data-analysis-lost-property-items-on-the-transport-of-london-5ffa519b24a6

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/c778e0a975ba973f737a2d175047e73f.png

伦敦地铁,图片由作者提供

如读者可能猜测的那样,这个故事有一个平凡的开始:我在公交车上忘了我的包。五分钟后,我意识到包不见了,但公交车已经离开了。回到家后,我查看了公交公司的网站,看看是否有认领丢失包的可能性,几天后,我很幸运地把它找回来了。我住在阿姆斯特丹,这里的公共交通与iLost公司有合作关系,人们可以认领他们丢失的物品。这个网站结构相当清晰,甚至不需要注册就可以查看不同人遗忘的物品(显然,个人详细信息是隐藏的)。拥有一种数据导向的思维,我得到了一个“啊哈”的时刻——这类数据从文化人类学的角度来看可以非常棒,我们可以了解到在公共交通和其他地方可能会丢失哪些物品。唉,iLost 的许可协议不允许在没有书面同意的情况下使用数据,而且没有人回应我的问题。但仍然抱着这个想法,我开始在网上寻找替代来源,结果发现:

  • 伦敦交通局(TfL)也为认领失物提供了良好的服务。

  • 英国有一部《信息自由法》(Freedom of Information Act),它为公共当局持有的信息创造了一个公共“获取权”。每个人都有权免费提出请求,并在 20 个工作日内得到回复。因此,我要求 TfL(如果可能的话)发送一个包含“原始数据”的 CSV 文件给我,2-3 周后(正如承诺的那样,并不快:),我确实收到了文件。我还询问了一名 TfL 官员我是否可以使用这些数据为我的 TDS 出版物,我得到了肯定的答复。

我认为这是一个很棒的服务(顺便说一句,美国自 1967 年以来就有了类似的法案),是科学家和数据爱好者使用公共数据进行研究的好机会。所以,无需多言,让我们看看我们可以得到哪些信息。如果有人想获取原始文件的副本以重现结果,请在下面写一条评论,我会分享链接。

加载数据

首先,让我们加载数据,看看它具有哪些维度和类型:

import pandas as pd

df = pd.read_csv("tfl.csv")
display(df.head())
display(df.info(verbose=True))

输出看起来是这样的:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/ed9003446acd9f0bb6f2885dc6da93dc.png

数据框摘要,图片由作者提供

如我们所见,我们有 5245 件物品,数据框中没有 NULL 项。日期格式看起来不规范,所以让我们将其转换:

df["Date Found"] = pd.to_datetime(df["Date Found"], format="%d/%m/%Y")

作为下一步,让我们弄清楚我们有哪些类别:

display(df["Category"].unique())

输出显示,这个数字并不大:

array(['Bags', 'Electronics & Technology', 'Wallets & Purses',
       'Baby & Nursery', 'ID & Personal Documents', 'Health & Beauty',
       'Tools / Garden / DIY', 'Jewellery', 'Travel Cards & Ticket',
       'Household & General Items', 'Keys', 'Sports & Leisure', 'Eyewear',
       'Currency (cash)', 'Stationery & Books', 'Clothing',
       'Financial Documents'], dtype=object)

为了使可视化看起来更好,我决定将“电子产品与技术”类别重命名为“电子产品”,并将所有“文档”类别合并为一个:

def update_category(name: str) -> str:
    """ Update category name """
    if "Documents" in name:
        return "Documents"
    if "Electronics" in name:
        return "Electronics"
    return name

df["Category"] = df["Category"].map(update_category)

在日期和类别转换后,我们的最终数据框看起来是这样的:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/5c685a42b9d486dd0d578e83d79a2685.png

图片由作者提供

每日物品数量

现在,我们准备享受一些乐趣。让我们按日期对所有物品进行分组并绘制一个条形图

import plotly.express as px

gr_day = df[["Date Found"]].groupby(["Date Found"], as_index=False).size()

fig = px.bar(gr_day, x="Date Found", y="size",
             title="<span style='font-size:18px;'><b>TfL, Lost Items Per Day</b></span><b></b>",
             width=1280, height=500)
fig.update_xaxes(tickformat="%a, %d-%m-%Y", showline=True, linecolor="black")
fig.update_layout(xaxis_title=None, yaxis_title=None, plot_bgcolor="#F5F5F5",
                  margin=dict(l=50, r=50, t=30, b=50))
fig.show()

在这里,我使用了开源的Plotly库来构建图表。这个库基于plotly.js,因此我们可以使用 HTML 格式化来更改样式。输出也是交互式的,我们可以在笔记本中直接缩放或移动图像。

输出看起来是这样的:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/aa8879987a0889e9aac3b025d02b60e8.png

每天丢失物品图表,图片由作者提供

有这些结果,计算在公共交通工具上丢失物品的概率很有趣。我不知道这些特定日子上的确切乘客数量,但一般来说,我们知道伦敦的公共交通每天处理大约 600 万次乘客行程。正如我们从图表中可以看到的,丢失物品的数量相当稳定。简单的计算表明,在交通中丢失物品的概率大约是 0.01%。这个数值本身并不大,但也不是微不足道的一一对于每 10000 人,每天至少有一个人可能会发生这种事件。

另一个有趣的发现是周四有一个峰值。我不知道为什么会出现这种情况,但另一个 TfL 新闻稿也提到了周四作为乘客数量最多的一天。这背后有什么社会解释吗?我不知道,但看起来很有趣。

类别

作为下一步,让我们按类别和子类别对所有商品进行分组:

gr_cat = df[["Category",
             "Sub-Category"]].groupby(["Category",
                                       "Sub-Category"], as_index=False).size()

我尝试了不同类型的可视化,其中两种,在我看来,最有信息量。首先,让我们绘制一个太阳花图,这是一种二维饼图:

fig = px.sunburst(gr_cat, width=1280, height=800,
                  path=["Category", "Sub-Category"], values="size",
                  color="Category",
                  title="<span style='font-size:18px;'><b>TfL, Lost Items Chart</b></span><b></b>"
                  )
fig.update_layout(font_size=10, margin=dict(l=10, r=10, t=30, b=50))
fig.update_traces(textinfo="label+percent parent")
fig.show()

输出看起来是这样的:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/2d08b74a3ee448dfff69b7dc580fb272.png

太阳花图,图片由作者提供

比较不同的部分很容易;例如,我们可以看到“包”和“电子产品”在我们的“丢失图表”中位居前列(分别为 19%和 15%)。在“包”类别中,乘客最常丢失的是背包(36%)。这从实际意义上来说是有道理的,因为背着背包站立或坐着并不方便,所以人们会取下它们。在“电子产品”类别中,手机位居首位(58%)。至于其他类别,10%的不幸乘客丢失了文件,4%的人丢失了钥匙。

一个旭日图看起来很有趣,但可能难以阅读狭窄的部分。另一个选择是树状图

fig = px.treemap(gr_cat, width=1280, height=800,
                 path=['Category', 'Sub-Category'], values='size',
                 color='Category')
fig.update_traces(textinfo="label+percent parent")
fig.show()

输出看起来像这样:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/255f90e03983eff295e2d9a931a56d9a.png

一个树状图,图片由作者提供

在这种情况下,通过将鼠标悬停在它们上,更容易读取较小子类别的数据。另一方面,使用饼图,更容易把握不同类别的相对大小。

子类别

让我们更详细地研究一下“电子产品”类别。为此,我们可以过滤数据框,按子类别分组所有项目,并绘制条形图:

df_ = df[df["Category"] == "Electronics"]
gr_electronics = df_[["Sub-Category"]].groupby(["Sub-Category"], as_index=False).size().sort_values(by="size", ascending=True)

fig = px.bar(gr_electronics, width=1280, height=600, 
             title="<span style='font-size:18px;'><b>TfL, Lost Items Per Week, Electronics</b></span><b></b>",
             x="size", y="Sub-Category", orientation="h")
fig.update_layout(xaxis_title="Amount", yaxis_title=None,
                  plot_bgcolor="#F5F5F5",
                  margin=dict(l=50, r=50, t=30, b=50))
fig.show()

在这里,我使用了水平条形图,因为它更容易阅读标签。输出看起来像这样:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/7d68c6bfad4a792a3b53486aa01af49a.png

图片由作者提供

如我们所见,大多数乘客都丢失了手机或手机配件,这看起来很明显。有些人设法丢失了笔记本电脑、平板电脑或电子阅读器,有一位乘客丢失了一个 MP3 播放器(如今这类设备已不太常见)。令人惊讶的是,这些数字相当大。数据集代表了一周的数据,正如我们所见,在这段时间内有 467 名乘客丢失了他们的手机。

位置

作为热身,让我们按位置分组数据,并获取一些商品被找到的前 10 个地方

gr_location = df[["Location"]].groupby(['Location'], as_index=False).size().sort_values(by="size", ascending=False)
display(gr_location[:10])

输出看起来像这样:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/493180cbcb9abb9efb789a17775799bc.png

图片由作者提供

我去过伦敦几次,但我的伦敦车站知识并不好。让我们在地图上绘制所有位置,这样更容易看到这些地方。我将使用 Python geopy库来获取坐标

from geopy.geocoders import Nominatim

geolocator = Nominatim(user_agent="Python3.9")

@lru_cache(maxsize=None)
def get_coord_lat_lon(full_addr: str) -> Tuple[float, float]:
    """ Get coordinates for address """
    pt = geolocator.geocode(full_addr + ", London, UK")
    return (pt.latitude, pt.longitude) if pt else (None, None)

在这里,我使用了lru_cache装饰器,如果我想多次运行代码,这可能很有帮助;数据将从缓存中获取,而不是进行新的 API 调用。我还使用了tqdm Python 库,它允许我在处理过程中看到进度条——这很有用,因为整个过程需要几分钟:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/3e6d8d36e8cead8d95dda6808d8f353e.png

当处理完成后,数据框看起来像这样:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/981dfd537cee60ca2e6f5f95fc7bd49e.png

图片由作者提供

现在,我们准备绘制地图。我将使用folium Python 库来完成这项工作:

import folium
from branca.element import Figure

fig = Figure(width=1024, height=600)
fmap = folium.Map(location=(51.5, -0.104),
                 tiles="openstreetmap", zoom_start=12)

for _, row in gr_location.iterrows():
    point = row["Coordinates"]
    name, amount = row["Location"], row["size"]
    if point[0] is not None or point[1] is not None:
        add_to_map(fmap, name, point, amount)

fig.add_child(fmap)
display(fig)

我还创建了add_to_mapvalue_to_color方法,这些方法有助于将站点添加到地图上:

def value_to_color(value: int) -> str:
    """ Convert value to the HTML color """
    norm = matplotlib.colors.Normalize(vmin=0, vmax=255, clip=True)
    mapper = colormap.ScalarMappable(norm=norm, cmap=colormap.inferno)
    r, g, b, _ = mapper.to_rgba(value, alpha=None, bytes=True)
    return "#" + f"{(r << 16) + (g << 8) + b:#08x}"[2:]

def add_to_map(fmap: folium.Map, name: str,
               location: Tuple[float, float],
               value: int):
    """ Add point to the map """
    color_str = value_to_color(value)
    folium.Circle(
        location=location,
        radius=10*value//2,
        popup = name + ": " + str(value),
        color=color_str,
        fill=True,
        fill_color=color_str
    ).add_to(fmap)

结果看起来是这样的:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/d84e5739af5edbca5b8f923d10bbf1cf.png

带有标记的伦敦地图,图片由作者提供

显然,这张地图显示了货物被发现的地方,但我们不知道它们丢失在哪里(尤其是在火车上,因为火车移动得很快),但看到结果仍然很有趣。显然,地图上最大的圆圈是最后的火车站或汽车站,但也有很多物品在其他车站被发现。有兴趣的读者也可以更改参数,如颜色图(我使用了“Inferno”调色板)和圆圈大小,以获得更好的可视化效果。

结论

在这篇文章中,我描述了向官方机构请求公共数据的可能性,我们能够分析这些数据,并得到了关于伦敦运输中丢失的财产物品的有趣结果。一般来说,让人们获取公共信息是一个伟大的想法,可以帮助研究人员和数据爱好者找到有趣的数据片段。无论如何,统计学是一门关于我们的科学。至于结果,我们可以看到在公共交通工具上丢失东西的概率是 0.01%,我希望所有读者在未来不要成为这个统计数据的一部分 😉

对社会数据分析感兴趣的人也可以阅读其他文章:

如果你喜欢这个故事,请随意订阅Medium,你将在我新文章发布时收到通知,以及访问成千上万其他作者故事的完整权限。你也很欢迎通过LinkedIn与我联系。如果你想要获取这篇和其他文章的完整源代码,请随意访问我的Patreon 页面

感谢阅读。

基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究(Matlab代码实现)内容概要:本文围绕“基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究”,介绍了利用Matlab代码实现配电网可靠性的仿真分析方法。重点采用序贯蒙特卡洛模拟法对配电网进行长时间段的状态抽样与统计,通过模拟系统元件的故障与修复过程,评估配电网的关键可靠性指标,如系统停电频率、停电持续时间、负荷点可靠性等。该方法能够有效处理复杂网络结构与设备时序特性,提升评估精度,适用于含分布式电源、电动汽车等新型负荷接入的现代配电网。文中提供了完整的Matlab实现代码与案例分析,便于复现和扩展应用。; 适合人群:具备电力系统基础知识和Matlab编程能力的高校研究生、科研人员及电力行业技术人员,尤其适合从事配电网规划、运行与可靠性分析相关工作的人员; 使用场景及目标:①掌握序贯蒙特卡洛模拟法在电力系统可靠性评估中的基本原理与实现流程;②学习如何通过Matlab构建配电网仿真模型并进行状态转移模拟;③应用于含新能源接入的复杂配电网可靠性定量评估与优化设计; 阅读建议:建议结合文中提供的Matlab代码逐段调试运行,理解状态抽样、故障判断、修复逻辑及指标统计的具体实现方式,同时可扩展至不同网络结构或加入更多不确定性因素进行深化研究。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值