Python 熊猫数据框基础知识
让我们从零开始了解熊猫数据框架的基本知识。
Credits: codebasics
在开始之前,让我先给你介绍一下 Pandas ,Pandas 是一个 python 库,它为 Python 编程语言的数据分析工具提供了高性能、易于使用的数据结构,如系列、数据框和面板。此外,Pandas 数据帧由主要组件组成,即数据、行和列。要使用熊猫的库和它的数据结构,你所要做的就是安装并导入它。要更好地理解和安装指南,请参阅 Pandas 库的文档。这里的完整代码可以在我的 GitHub 页面上找到。
可应用于熊猫数据框的基本操作如下所示。
- 创建数据框。
- 对行和列执行操作。
- 数据选择、添加、删除。
- 处理缺失数据。
- 重命名数据帧的列或索引。
1。创建数据框。
Pandas 数据框可通过从外部现有存储(如数据库、SQL 或 CSV 文件)加载数据来创建。但是熊猫数据帧也可以从列表、字典等创建。创建熊猫数据框的方法之一如下所示:
# import the pandas library
import pandas as pd
# Dictionary of key pair values called data
data = {'Name':['Ashika', 'Tanu', 'Ashwin', 'Mohit', 'Sourabh'],
'Age': [24, 23, 22, 19, 10]}
data**{'Age': [24, 23, 22, 19, 10], 'Name': ['Ashika', 'Tanu', 'Ashwin', 'Mohit', 'Sourabh']}**# Calling the pandas data frame method by passing the dictionary (data) as a parameter
df = pd.DataFrame(data)
df
2。对行和列执行操作。
数据帧是一种二维数据结构,数据存储在行和列中。下面我们可以对行和列执行一些操作。
**选择列:**为了选择一个特定的列,我们所能做的就是调用数据框内的列名。
# import the pandas library
import pandas as pd
# Dictionary of key pair values called data
data = {'Name':['Ashika', 'Tanu', 'Ashwin', 'Mohit', 'Sourabh'],
'Age': [24, 23, 22, 19, 10]}
data**{'Age': [24, 23, 22, 19, 10], 'Name': ['Ashika', 'Tanu', 'Ashwin', 'Mohit', 'Sourabh']}**# Calling the pandas data frame method by passing the dictionary (data) as a parameter
df = pd.DataFrame(data)
# Selecting column
df[['Name']]
选择行: Pandas 数据框提供了一个名为“loc”的方法,用于从数据框中检索行。此外,还可以通过使用“iloc”功能来选择行。
# Calling the pandas data frame method by passing the dictionary (data) as a parameter
df = pd.DataFrame(data)
# Selecting a row
row = df.loc[1]
row**Name Tanu
Age 23
Name: 1, dtype: object**
要选择一个特定的列,我们所能做的就是调用数据框内的列名。如上所述,要使用“loc”方法,您必须将数据框的索引作为参数传递。loc 方法只接受整数作为参数。所以在上面的例子中,我想访问“Tanu”行,所以我将索引 1 作为参数传递。现在给你们一个快速作业,用“iloc”方法,告诉我结果。
3。数据选择、添加、删除。
您可以在语义上将 DataFrame 视为一个相似索引系列对象的字典。获取、设置和删除列的语法与类似的字典操作相同:
# import the pandas library
import pandas as pd
# Dictionary of key pair values called data
data = {'Name':['Ashika', 'Tanu', 'Ashwin', 'Mohit', 'Sourabh'],
'Age': [24, 23, 22, 19, 10]}# Calling the pandas data frame method by passing the dictionary (data) as a parameter
df = pd.DataFrame(data)
# Selecting the data from the column
df['Age']**0 24
1 23
2 22
3 19
4 10
Name: Age, dtype: int64**
可以像使用字典一样删除列,只需使用 del 操作。
del df[‘Age’]
df
可以使用插入功能添加数据。插入功能可用于在列中的特定位置插入:
df.insert(1, ‘name’, df[‘Name’])
df
4。处理缺失数据。
当我们访问大数据集时,丢失数据会发生很多次。它经常像 NaN(不是数字)一样出现。为了填充那些值,我们可以使用“isnull()”方法。该方法检查数据帧中是否存在空值。
检查缺失值。
# importing both pandas and numpy libraries
import pandas as pd
import numpy as np# Dictionary of key pair values called data
data ={‘First name’:[‘Tanu’, np.nan],
‘Age’: [23, np.nan]}df = pd.DataFrame(data)
df
# using the isnull() function
df.isnull()
如果空值不存在,isnull()返回 false,如果为空值,则返回 true。现在我们已经找到了丢失的值,下一个任务是用 0 填充这些值。这可以如下所示完成:
df.fillna(0)
5。重命名数据帧的列或索引。
要为数据框的列或索引值赋予不同的值,最好使用。rename()方法。为了更好地理解,我特意更改了列名。
# import the pandas library
import pandas as pd
# Dictionary of key pair values called data
data = {‘NAMe’:[‘Ashika’, ‘Tanu’, ‘Ashwin’, ‘Mohit’, ‘Sourabh’],
‘AGe’: [24, 23, 22, 19, 10]}# Calling the pandas data frame method by passing the dictionary (data) as a parameter
df = pd.DataFrame(data)
df
newcols = {
‘NAMe’: ‘Name’,
‘AGe’: ‘Age’
}
# Use `rename()` to rename your columns
df.rename(columns=newcols, inplace=True)
df
# The values of new index
newindex = {
0: ‘a’,
1: ‘b’,
2: ‘c’,
3: ‘d’,
4: ‘e’
}
# Rename your index
df.rename(index=newindex)
以上是 Python 中熊猫数据框架的非常重要的技术或方法。一些例子是从 GeeksforGeeks 引用的。我用一种简单的方式写了这个,这样每个人都能理解和掌握 Python 中数据框的概念。如果你们对代码有什么疑问,评论区就是你们的了。
谢谢你。
Python、性能和 GPU
Python 中使用 GPU 加速器的状态更新
这篇博文是在最近的 PASC 2019 大会上以谈话形式发表的。 演讲的幻灯片在这里 。
行动纲要
我们正在改进 Python 中可扩展 GPU 计算的状态。
这篇文章展示了当前的状态,并描述了未来的工作。它还总结并链接了最近几个月的其他几篇博客文章,这些文章深入到不同的主题,供感兴趣的读者阅读。
概括地说,我们简要地涵盖了以下几个类别:
- 用 CUDA 写的 Python 库比如 CuPy 和 RAPIDS
- Python-CUDA 编译器,特别是 Numba
- 使用 Dask 扩展这些库
- 与 UCX 的网络通信
- 用康达包装
GPU 加速的 Python 库的性能
对于 Python 程序员来说,获得 GPU 性能的最简单方法可能就是使用 GPU 加速的 Python 库。这些提供了一组通用的操作,它们被很好地调整和集成在一起。
许多用户知道用于深度学习的库,如 PyTorch 和 TensorFlow,但还有其他几个用于更通用计算的库。这些倾向于复制流行的 Python 项目的 API:
这些库构建了流行 Python 库的 GPU 加速变体,如 NumPy、Pandas 和 Scikit-Learn。为了更好地理解相对性能差异 Peter Entschev 最近整理了一个基准测试套件来帮助进行比较。他制作了下图,展示了 GPU 和 CPU 之间的相对加速比:
那里有很多有趣的结果。彼得在他的博客中对此进行了更深入的探讨。
然而,更广泛地说,我们看到了性能的可变性。我们关于 CPU 快慢的心理模型并不一定适用于 GPU。幸运的是,由于一致的 API,熟悉 Python 的用户可以很容易地试验 GPU 加速,而无需学习 CUDA。
Numba:将 Python 编译成 CUDA
另见本 最近关于 Numba stencils 的博文以及附带的 GPU 笔记本
像 CuPy 和 RAPIDS 这样的 GPU 库中的内置操作,涵盖了最常见的操作。然而,在现实世界的设置中,我们经常会发现需要编写一些自定义代码的混乱情况。在这些情况下,切换到 C/C++/CUDA 可能会很有挑战性,尤其是对于主要是 Python 开发人员的用户。这就是 Numba 的用武之地。
Python 在 CPU 上也有同样的问题。用户通常懒得学习 C/C++来编写快速定制代码。为了解决这个问题,有像 Cython 或 Numba 这样的工具,它们让 Python 程序员无需学习 Python 语言以外的知识就能编写快速的数字代码。
例如,Numba 在 CPU 上将 For 循环风格的代码加速到 500 倍以下,从缓慢的 Python 速度提高到快速的 C/Fortran 速度。
**import** **numba** *# We added these two lines for a 500x speedup*
@numba.jit *# We added these two lines for a 500x speedup*
**def** sum(x):
total = 0
**for** i **in** range(x.shape[0]):
total += x[i]
**return** total
在不切换 Python 上下文的情况下下降到底层高性能代码的能力是有用的,特别是如果您还不知道 C/C++或者没有为您设置的编译器链的话(目前大多数 Python 用户都是这种情况)。
这种优势在 GPU 上更加明显。虽然许多 Python 程序员懂一点 C 语言,但很少有人懂 CUDA。即使他们这样做了,他们可能也很难设置编译器工具和开发环境。
进入 numba.cuda.jit Numba 的 cuda 后端。Numba.cuda.jit 允许 Python 用户以交互方式创作、编译和运行用 Python 编写的 cuda 代码,而无需离开 Python 会话。这是一个在 Jupyter 笔记本中编写模板计算来平滑 2d 图像的图像:
下面是 Numba CPU/GPU 代码的简化对比,比较编程风格。GPU 代码的速度比单个 CPU 内核快 200 倍。
CPU — 600 毫秒
@numba.jit
**def** _smooth(x):
out = np.empty_like(x)
**for** i **in** range(1, x.shape[0] - 1):
**for** j **in** range(1, x.shape[1] - 1):
out[i,j] = (x[i-1, j-1] + x[i-1, j+0] + x[i-1, j+1] +
x[i+0, j-1] + x[i+0, j+0] + x[i+0, j+1] +
x[i+1, j-1] + x[i+1, j+0] + x[i+1, j+1])//9 **return** out
或者如果我们使用花哨的 numba.stencil 装饰器…
@numba.stencil
**def** _smooth(x):
**return** (x[-1, -1] + x[-1, 0] + x[-1, 1] +
x[ 0, -1] + x[ 0, 0] + x[ 0, 1] +
x[ 1, -1] + x[ 1, 0] + x[ 1, 1]) // 9
GPU — 3 毫秒
@numba.cuda.jit
**def** smooth_gpu(x, out):
i, j = cuda.grid(2)
n, m = x.shape
**if** 1 <= i < n - 1 **and** 1 <= j < m - 1:
out[i, j] = (x[i-1, j-1] + x[i-1, j] + x[i-1, j+1] +
x[i , j-1] + x[i , j] + x[i , j+1] +
x[i+1, j-1] + x[i+1, j] + x[i+1, j+1]) // 9
Numba.cuda.jit 已经存在很长时间了。它容易接近,成熟,玩起来很有趣。如果你有一台装有 GPU 的机器,并有一些好奇心,那么我们强烈建议你尝试一下。
conda install numba
# or
pip install numba>>> **import** **numba.cuda**
使用 Dask 扩展
正如在以前的博客文章( 1 、 2 、 3 、 4 )中提到的,我们已经一般化了 Dask ,不仅可以操作 Numpy 数组和 Pandas 数据帧,还可以操作任何看起来足够像 Numpy(像 CuPy 或 Sparse 或 Jax )或足够像 Pandas(像【T16 这很有效。下面是一个简短的视频,展示了 Dask array 并行计算一个 SVD,并展示了当我们用 CuPy 替换 Numpy 库时会发生什么。
我们看到计算速度提高了大约 10 倍。最重要的是,我们能够在 CPU 实现和 GPU 实现之间切换,只需一行代码,但继续使用 Dask Array 的复杂算法,就像它的并行 SVD 实现一样。
我们也看到了交流的相对放缓。总的来说,今天几乎所有重要的 Dask + GPU 工作都变得与通信密切相关。我们的计算速度已经够快了,交流的相对重要性已经显著增加。
与 UCX 的通信
也参见 这篇最近关于 UCX 和达斯克 的博文
我们一直在用的 UCX-Py 将的 OpenUCX 库集成到 Python 中。UCX 提供对 TCP、InfiniBand、共享内存和 NVLink 等传输的统一访问。UCX-Py 是第一次可以从 Python 语言轻松访问这些传输协议。
一起使用 UCX 和 Dask,我们能够获得显著的加速。以下是添加 UCX 前后的 SVD 计算轨迹:
在 UCX 之前:
UCX 之后:
尽管如此,这里仍有大量工作要做(上面链接的博客文章在未来工作部分有几个条目)。
人们可以用高度实验性的康达套装试用 UCX 和 UCX-Py:
conda create -n ucx -c conda-forge -c jakirkham/label/ucx cudatoolkit=9.2 ucx-proc=*=gpu ucx ucx-py python=3.7
我们希望这项工作也将影响使用 Infiniband 的 HPC 系统上的非 GPU 用户,甚至是消费类硬件上的用户,因为他们可以轻松访问共享内存通信。
包装
在之前的博文中,我们讨论了安装与系统上安装的 CUDA 驱动程序不匹配的 CUDA 支持包的错误版本所带来的挑战。幸运的是,由于 Anaconda 的 Stan Seibert 和 Michael Sarahan 最近的工作,Conda 4.7 现在有了一个特殊的元包,它被设置为已安装驱动程序的版本。这将使用户在未来安装正确的软件包变得更加容易。
Conda 4.7 刚刚发布,除了cuda
元包之外,还有许多新特性。你可以在这里了解更多信息。
conda update conda
今天在包装领域仍有大量的工作要做。每个构建 conda 包的人都用自己的方式,导致头痛和异构。这很大程度上是因为没有集中的基础设施来构建和测试支持 CUDA 的包,就像我们在 Conda Forge 所做的那样。幸运的是,Conda Forge 社区正在与 Anaconda 和 NVIDIA 合作来帮助解决这个问题,尽管这可能需要一些时间。
摘要
这篇文章更新了 Python 中 GPU 计算背后的一些努力。它也为将来的阅读提供了各种各样的链接。如果您想了解更多信息,我们在下面列出了它们:
- 幻灯片
- GPU 上的 numpy:CuPy
- GPU 上的 Numpy(再次): Jax
- GPU 上的熊猫:激流 cuDF
- sci kit-在 GPU 上学习: RAPIDS cuML
- 基准测试套件
- 数字 CUDA JIT 笔记本
- 关于 UCX 的演讲
- 一篇关于 UCX 和达斯克的博文
- 康达 4.7
Python 预测 PUBG 移动
使用 Python 预测视频数据中未来帧的简单方法
My PUBG character 😄
简介:
预测未来是不可能的!(除非你有 时间石 -😃 )。但是预测不远的将来对我们来说并不难。我们在现实生活中经常这样做——在玩游戏或看电影时,人们可以很容易地预测即将发生的事情。我们大脑的这种能力有助于我们提前计划行动和做出决定。(例如,在空中接球,躲避迎面而来的石头……等等)。
我们不能躲避子弹,因为我们不够快。如果我们能把大脑的这种能力给愚蠢的机器,然后造一个奥创 -:)会怎么样。
问题是——机器真的能做到吗?
答案是肯定的。这个小实验证明了这一点。这也是一个活跃的研究领域——给定一个小视频,你能生成未来的视频吗?这是这个实验产生的数据的一瞥—
下面的视频完全是人工的,由深度学习模型生成。
Artificially Generated Video
如何在我的电脑上完成?
只需几个小时,你就可以在自己的电脑上完成。也不需要 GPU。
如果你是计算机视觉和深度学习的新手,我建议你在进一步阅读之前对以下主题有一个基本的了解—
现在让我们把整件事分成五个小部分。我们将一个接一个地检查每一部分——
- 数据生成
- 数据准备
- 型号
- 结果
- 结论
数据生成:
生成数据非常简单。在我的移动设备上的屏幕录制器的帮助下,我能够捕捉到一个 15 分钟长的视频(事实证明这对我们的小实验来说是足够的数据)。在这个视频中,我将我的 PUBG 角色设置为冲刺模式,让它在随机方向上连续跑大约 15 分钟。
一旦我有了这个视频,我需要做的就是按固定的时间间隔将它切割成多个帧。使用OpenCV toolkit
,这种视频到帧的转换非常简单快捷。这些帧相距大约~25ms
,这使得它成为**40fps (frames per second)**
。两个连续帧之间的差异很小,但相当明显。
这是一个简单的 python 代码,它将视频转换为帧。(*不同机器上的帧速率可能有所不同,因为它取决于您系统的处理速度。)
Video to Frame conversion
数据准备:
之前的练习给了我们大约 30k 帧。在这 30k 帧中,前 29k 帧作为训练数据,其余 1k 帧作为验证数据。
这些相框的尺寸真的很大800 * 1200
。为了使模型简单快速,在将每一帧传递给模型进行训练之前,将每一帧的大小调整为240 * 160
。
下面是一个用于数据预处理的简单 python 函数。
Preprocessing function
这是处理过的图像的样子——
在 1 之后。裁剪图像,仅保留图像的相关部分。
第二年。将图像调整为较小的尺寸(240*160),因为原始图像非常大。(调整图像大小时,纵横比保持不变)。
Image preprocessing
型号:
- 训练数据:
来自先前练习的预处理帧成对排列,使得每对帧(frame_x, frame_y)
具有两个连续的帧——例如,如果frame_x
出现在视频中的n’th
位置,那么frame_y
应该来自(n+1)’th
位置。
以这种方式,我们为训练数据保留的那些 29k 帧可以构成29k — 1
这样的训练数据对。类似地,剩余的 1k 验证帧可以构成 1k 验证数据对。
2。模型架构:
Encoder — Decoder Architecture
在该实验中使用了简单的 编码器-解码器 模型架构。这里的encoder
部分模型是一个三层的2D CNN (convolutional neural network)
和MaxPooling
层。该模型的decoder
部分也是2D CNN with UpSampling layers
或(转置卷积神经网络)。卷积层的核大小保持不变,以便我们在解码后得到相同大小的图像。
下面是使用 tensorflow 的 keras api 实现的模型的架构。
Model Architecture
3。模型训练:
现在,对于每个训练对,模型将frame_x
作为输入,并学习猜测frame_y
(下一个直接帧)。
采用梯度下降算法训练模型,以mean squared error
为损失函数……
**--- Model Parameters ---**
batch_size : 32
epochs : 10
optimizer : 'adam'
learning_rate : 0.001
loss : 'mse'
在仅仅训练10 epochs
之后,学习的权重被保存用于推断。
Training time : approximately 8 hours (on CPU)
Hardware : Macbook Pro, 16GB, 2.6 GHz, Intel Core i7
培训和验证损失图
Loss Chart
结果:
为了检查模型在看不见的数据上的性能,从验证集中选取一个随机帧。现在,使用这个单一的帧,我们可以通过将预测的帧一次又一次地传递给模型作为输入来生成任意数量的未来帧。
模型能够从单个输入帧生成前 10-12 个未来帧,具有相当高的精度。在第 15 帧之后,它变得非常嘈杂,因为预测误差在每次新的预测时都会增加。需要注意的一件重要事情是static parts of the frames (my PUBG control buttons) are intact as model is able to learn what is static and what is changing
这部分也不会模糊。
下面是由模型生成的两个示例图像序列,以及顶部的地面真实图像。
Image sequences generated by model
结论:
有趣的是,这个模型能够很容易地用一张图像生成这么多未来的图像。这很简单,因为这个实验是受控的 PUBG 视频中的人只进行一项活动(总是跑步)。因此,模型只需要学习他的运动以及背景如何随时间变化。
预测真实的生活场景并不容易。这也是一个活跃的研究领域。这很难,因为在现实世界中有无限的可能性。多个对象可以同时改变环境。为了对这样的场景建模,我们需要一个更好、更强大的模型架构。还有大量高质量的真实世界数据。
感谢 Raghav Bali 和 Dipanjan (DJ) Sarkar 的点评。
请与我分享您的意见/反馈。
Python Pro 提示:开始使用 Python defaultdict 和 Counter 代替字典
蟒蛇短裤
如何使用 defaultdict 和 Counter 使你的代码简短易读
Photo by Brooke Lark on Unsplash
学习一门语言很容易。每当我开始学习一门新的语言时,我会按照下面的顺序专注于几件事情,开始用任何语言编写代码都是轻而易举的事情。
- 运算符和数据类型:+,-,int,float,str
- 条件语句:if,else,case,switch
- 循环:For,while
- 数据结构:列表,数组,字典,散列表
- 定义函数
但是,学会写语言和用优化的方式写语言是两回事。
每种语言都有一些独特的成分。
然而, 一个新的程序员对任何语言总会做一些被迫的过度适应。 举例来说,一个刚接触 python 的 Java 程序员,可能会编写这段代码来添加列表中的数字。
x=[1,2,3,4,5]sum_x = 0
for i in range(len(x)):
sum_x+=x[i]
虽然 python 程序员会很自然地这样做:
sum_x = sum(x)
在这一系列名为**‘Python Shorts’**的帖子中,我将解释由 Python 提供的一些简单构造、一些基本技巧以及我在数据科学工作中经常遇到的一些用例。
这个系列讲的是高效可读的代码。
计数器和默认值—用例
假设我需要统计一段文本中出现的单词数。 也许对于《哈姆雷特》这样的书来说。我怎么能这么做呢?
Python 总是为我们提供多种方法来做同样的事情。但只有一种方式我觉得很优雅。
这是一个使用dict
对象的 幼稚 Python 实现 。
text = "I need to count the number of word occurrences in a piece of text. How could I do that? Python provides us with multiple ways to do the same thing. But only one way I find beautiful."word_count_dict = {}
for w in text.split(" "):
if w in word_count_dict:
word_count_dict[w]+=1
else:
word_count_dict[w]=1
我们可以使用***defaultdict***
来减少代码中的行数。
from collections import defaultdict
word_count_dict = defaultdict(int)
for w in text.split(" "):
word_count_dict[w]+=1
我们也可以使用***Counter***
来做到这一点,在我看来,这是解决这个问题的最佳方法。
from collections import Counter
word_count_dict = Counter()
for w in text.split(" "):
word_count_dict[w]+=1
如果我们使用Counter
,我们也可以使用一个简单的函数得到最常见的单词。
word_count_dict.most_common(10)
---------------------------------------------------------------
[('I', 3), ('to', 2), ('the', 2)]
计数器的其他使用案例:
# Count Characters
Counter('abccccccddddd')
---------------------------------------------------------------
Counter({'a': 1, 'b': 1, 'c': 6, 'd': 5})# Count List elements
Counter([1,2,3,4,5,1,2])
---------------------------------------------------------------
Counter({1: 2, 2: 2, 3: 1, 4: 1, 5: 1})
那么,为什么曾经使用过defaultdict
?
注意在Counter
中,值总是一个整数。
如果我们想解析一个包含颜色和水果的元组列表会怎么样。并希望创建一个键和值列表的字典。
一个defaultdict
提供的主要功能是,如果在defaultdict
中没有找到,它默认一个键为空/零。
s = [('color', 'blue'), ('color', 'orange'), ('color', 'yellow'), ('fruit', 'banana'), ('fruit', 'orange'),('fruit','banana')]d = defaultdict(list)for k, v in s:
d[k].append(v)print(d)
---------------------------------------------------------------
defaultdict(<class 'list'>, {'color': ['blue', 'orange', 'yellow'], 'fruit': ['banana', 'orange', 'banana']})
banana
在fruit
中出现两次,我们可以用set
d = defaultdict(set)for k, v in s:
d[k].add(v)print(d)
---------------------------------------------------------------
defaultdict(<class 'set'>, {'color': {'yellow', 'blue', 'orange'}, 'fruit': {'banana', 'orange'}})
结论
总结一下,我要说的是 在Python中总有一种做任何事情的美好方式。在编写代码之前搜索它。去 StackOverflow 没问题。我被困的时候去过很多次。永远记住:
为已经提供的东西创建一个函数不是 pythonic 式的。
另外,如果你想了解更多关于 Python 3 的知识,我想向你推荐密歇根大学的一门优秀的中级 Python 课程。一定要去看看。
将来我也会写更多初学者友好的帖子。让我知道你对这个系列的看法。在 媒体 关注我,或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系。
Python Pro 提示:使用迭代器、生成器和生成器表达式
蟒蛇短裤
对于编码来说,理解是至关重要的
Photo by Aziz Acharki on Unsplash
谈到编程,Python 在很多方面都让我们的生活变得更加轻松。
它有许多库和功能,有时我们会忘记关注它提供的一些有用的东西。
其中一个功能是生成器和生成器表达式。我拖延了很长时间去学习它们,但是它们很有用。
你有没有在 Python 代码中遇到过yield
而不知道它是什么意思?或者一个iterator
或一个generator
是什么意思,我们为什么使用它?或者你在使用 Keras 的时候使用过ImageDataGenerator
却不明白后端发生了什么?那么这篇文章是给你的。
在这一系列名为**'Python Shorts,‘**的帖子中,我将解释 Python 提供的一些简单构造、一些基本技巧以及我在数据科学工作中经常遇到的一些用例。
这篇文章是关于用一种简单易懂的方式解释一些难懂的概念。
问题陈述:
假设我们需要运行一个超过 1000 万素数的 for 循环。
为了便于理解,我在这种情况下使用质数,但它可以扩展到我们必须处理数据库或大数据中的大量图像或文件的情况。
你会如何处理这样的问题?
简单。我们可以创建一个列表,将所有的质数保存在那里。
真的吗? 想想这样一个列表会占用多少内存。
如果我们有某种东西可以保存我们检查过的最后一个素数,并返回下一个素数,那就太好了。
这就是迭代器可以帮助我们的地方。
迭代器解决方案
我们创建了一个名为素数的类,并用它来生成素数。
def check_prime(number):
for divisor in range(2, int(number ** 0.5) + 1):
if number % divisor == 0:
return False
return Trueclass Primes:
def __init__(self, max):
# the maximum number of primes we want generated
self.max = max
# start with this number to check if it is a prime.
self.number = 1
# No of primes generated yet. We want to StopIteration when it reaches max
self.primes_generated = 0
def __iter__(self):
return self
def __next__(self):
self.number += 1
if self.primes_generated >= self.max:
raise StopIteration
elif check_prime(self.number):
self.primes_generated+=1
return self.number
else:
return self.__next__()
然后,我们可以将它用作:
prime_generator = Primes(10000000)for x in prime_generator:
# Process Here
这里我定义了一个迭代器。这就是大多数像xrange
或ImageGenerator
这样的功能是如何工作的。
每个迭代器都需要:
- 一个返回 self 的
__iter__
方法,以及 - 返回下一个值的
__next__
方法。 - 表示迭代器结束的异常。
每个迭代器都采用上述形式,我们可以根据自己的喜好在样板代码中调整函数来做我们想做的事情。
注意,我们并没有把所有的质数都保存在内存中,只是保存了迭代器的状态,就像
- 我们返回的最大质数是多少
- 我们已经归还了多少质数。
但是代码好像有点多。我们能做得更好吗?
发电机解决方案
Simple yet beautiful…
简而言之,生成器为我们提供了使用yield
语句轻松编写迭代器的方法。
def Primes(max):
number = 1
generated = 0
while generated < max:
number += 1
if check_prime(number):
generated+=1
yield number
我们可以将该函数用作:
prime_generator = Primes(10)
for x in prime_generator:
# Process Here
读起来简单多了。但是什么是yield
?
我们可以认为yield
是一个return
语句,只是因为它返回值。
但是当yield
发生时,功能的状态也被保存在存储器中。所以在 for 循环的每次迭代中,像number, generated and max
这样的函数变量都存储在内存中的某个地方。
因此,上面的函数通过使用yield
语句为我们处理所有的样板代码。
更像蟒蛇。
Generator Expression Solution
So Much Cleaner!!!
虽然没有明显优于前面的解决方案,但我们也可以使用生成器表达式来完成相同的任务。但是我们可能会失去一些功能。它们的工作方式与列表理解完全一样,但它们不会将整个列表保存在内存中。
primes = (i for i in range(1,100000000) if check_prime(i))for x in primes:
# do something
功能损失:我们可以产生 1000 万个素数。但是我们不能产生 1000 万个素数。对于生成器表达式,我们只能做这么多。
但是生成器表达式让我们做了一些很酷的事情。
假设我们希望所有的毕达哥拉斯三元组都小于 1000。
怎么才能得到呢?
使用发电机,现在我们知道如何使用它们。
def triplet(n): # Find all the Pythagorean triplets between 1 and n
for a in range(n):
for b in range(a):
for c in range(b):
if a*a == b*b + c*c:
yield(a, b, c)
我们可以这样使用:
triplet_generator = triplet(1000)for x in triplet_generator:
print(x)------------------------------------------------------------
(5, 4, 3)
(10, 8, 6)
(13, 12, 5)
(15, 12, 9)
.....
或者,我们也可以在这里使用生成器表达式:
triplet_generator = ((a,b,c) for a in range(1000) for b in range(a) for c in range(b) if a*a == b*b + c*c)for x in triplet_generator:
print(x)------------------------------------------------------------
(5, 4, 3)
(10, 8, 6)
(13, 12, 5)
(15, 12, 9)
.....
Python 不好看吗?
我讨厌中等代码块,有时是因为代码中断和复制粘贴问题。所以你可以看到这个 kaggle 内核中的所有代码。
结论
我们必须时刻努力减少Python中的内存占用。迭代器和生成器为我们提供了一种通过惰性求值来实现的方法。
我们如何选择使用哪一个?我们可以用生成器表达式做什么,我们也可以用生成器或迭代器做什么。
这里没有正确答案。每当我面临这样的困境时,我总是从功能性和可读性的角度来考虑。一般来说,
功能方面:迭代器>生成器>生成器表达式。
可读性:来自密歇根大学的迭代器
It is not necessary that you end up using them in your code now. But I guess understanding how these things work helps mitigate some of the confusion and panic one faces whenever these constructs come up.
Understanding is vital when it comes to coding
Also if you want to learn more about Python 3, I would like to call out an excellent course on Learn 中级 Python 。一定要去看看。
将来我也会写更多初学者友好的帖子。让我知道你对这个系列的看法。在 中 关注我,或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系到我。
Python Pro 提示:想在 Python 中使用 R/Java/C 或者任何语言?
蟒蛇短裤
Python 提供了一种基本而简单的方法来处理这样的需求,我们必须在多种语言之间来回切换
巨蟒 很棒。真的很棒。
但是随着时间的推移,这个领域变得/将变得与语言无关。许多伟大的工作正在用许多其他语言完成。
虽然我仍然把 Python 作为主要语言,但如果它能完成工作,我会毫不犹豫地转向另一种语言。
事实上,每一种语言都以这样一种方式进化,它在某些领域建立了自己的据点。例如, 有些人可能会发现使用 R 进行回归更容易,或者在 R 中使用 ggplot 进行绘图(尽管我真诚地感到 Python 已经在 可视化 部门取得了长足的进步。)
有时是因为某个特定的库是用 Java/C 编写的,而有人还没有把它移植到 Python 上。
但是有没有更好的方法来处理这种不断的麻烦呢?
我喜欢 Python 是因为我现在很好的理解了它。与用 R 或 Java 或 Scala 相比,用 Python 做这么多事情对我来说很容易。
如果我只想使用 R 中的线性回归包,为什么我必须在 R 中编写我的数据准备步骤?
或者如果我只想使用 Stacknet 包,为什么我必须学习用 Java 创建图表?
现在 Python 和 R 有了很多包装器。如何在 Python 中使用 R 或者如何在 R 中使用 Python?rpy2
和reticulate
这些套餐都不错,可能会解决一些问题。但是他们没有解决一般性的问题。每次我想从一种语言切换到另一种语言时,我都需要学习一个全新的包/库。完全不可伸缩。
在这一系列名为 Python Shorts 的帖子中,我将解释 Python 提供的一些简单构造,一些必要的技巧和我在数据科学工作中经常遇到的一些用例。
这篇文章是关于利用另一种语言的一个特殊的包/库,同时不离开用我们的主要语言编码的舒适。
问题陈述
我将从一个问题陈述开始解释这一点。假设我不得不使用 R 创建一个图表,但是我想用 Python 准备我的数据。
这是任何数据科学家都可能面临的普遍问题。用一种语言做一些事情,然后转到另一种语言做一些其他的事情。
不离开 Jupyter 笔记本就能做到吗?还是我的 Python 脚本?
解决方案
以下是我如何实现这一点。对一些人来说,这可能看起来很黑客,但我喜欢黑客。
import pandas as pd
data=pd.read_csv("data.csv")
data = preprocess(data)data.to_csv("data.csv",index=None)
os.system("Rscript create_visualization.R")
***os.system***
命令为我提供了一种使用 Python 访问我的 shell 的方法。外壳是你可以随意使用的有力的工具。您几乎可以在 shell 上运行任何语言。
将在 python 中运行的相应的Rscript
看起来类似于:
*data<-read.table("data.csv")
ggplot(...)
ggsave("plot.png")*
然后,我可以加载 png 文件,并使用类似 markdown hack 的工具在我的 Jupyter 笔记本上显示它。
**
对于不想离开 R 的舒适环境的 R 用户来说,R 还有一个类似于os.system
的system
命令,可以用来在 R 中运行 Python 代码
结论
中的***os.system***
Python通过让我们从 Python 中调用 shell 命令,为我们提供了一种在 Python 中做每一件事的方法。
我已经在我的很多项目中使用了它,在这些项目中,我使用 Mutt 发送电子邮件。或者运行一些 Java 程序或者瞎搞。
这看起来像是一种不成熟的方法,但是它很有效,而且足够一般化,以至于当你想用任何其他语言做一些事情并将其与 Python 集成时,你不必学习一个新的库。
如果你想了解更多关于 Python 3 的知识,我想从密歇根大学调出一门关于学习中级 Python 的优秀课程。一定要去看看。
将来我也会写更多初学者友好的帖子。让我知道你对这个系列的看法。在关注我或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系。
Python range()内置函数
让我们了解一下 python 中 range()函数的基础知识。
现在让我们来理解 python 中 range 函数()的概念,下面展示的概念和例子将帮助你们以一种清晰的方式理解 range()。另外,请访问我的 GitHub 库,在下面找到更多关于 range 函数的详细信息:
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/Tanu-N-Prabhu/Python/blob/master/Range_built_in_function.ipynb)
我们开始吧!!!
定义
range()函数是 python 中使用的内置函数,用来生成一个数列。如果用户希望在给定起始值和结束值的情况下生成一个数字序列,那么他们可以将这些值作为 range()函数的参数。range()函数将根据用户的要求生成一系列数字。
句法
range()函数的语法如下所示:
**range(start, stop, step)**
因素
range()内有三个参数:开始,停止,步进。当您考虑这三个参数时,它类似于下面将要讨论的真实场景。
***Start:*** *Optional — An integer number that specifies where to start (Default value is 0)***Stop**: Required — An integer number that specifies where to stop.**Step:** Optional — An integer number that specifies how much to increment the number (Default value is 1)
返回值
range 函数的返回值是一系列数字,具体取决于所定义的参数。
例题
1。让我们看看当我们打印值为 10 的 range 函数时会发生什么。
x = range(10)
print(x)**range(0, 10)**
如上所示,值 10 表示范围功能的终止值,0 值默认作为起始值添加。
2。让我们看看当我们把 range 函数放入 for 循环时会发生什么。
x = range(10)
for i in x:
print(i)**0
1
2
3
4
5
6
7
8
9**
如上所示,我们可以得到从 0 到 10 的值,但不包括 10,因为范围函数的停止值总是返回值-1 。因此值为 0-10。
3。让我们看看,当我们给 range 函数一个起始值和终止值时,会发生什么。
x = range(1, 10)
for i in x:
print(i)**1
2
3
4
5
6
7
8
9**
如上所示,它打印出从 1 到 9 的值,因为起始值被定义为 1。
4。让我们看看当我们给距离函数一个步长值时会发生什么。
x = range(1, 10, 2)
for i in x:
print(i)**1
3
5
7
9**
如上所述,步长用于增加数字,在这种情况下,步长为 2,因此数字增加 2。
一般来说,可以这样认为范围函数就像现实生活中的场景:
- 你开始走— 开始
- 你踏出你的步伐(脚步)——步
- 你停下来行走,因为你已经到达了目的地。
即使在这种情况下你没有声明 step 变量,你也会一次走一步,显然,没有人会一次走两步。
范围函数的类型为 class
是的,range 函数是一个类,因为当你使用 type()检查 range 函数的类型时,你就会得到答案。
x = range(10)
print(type(x))**<class 'range'>**
不要在 range 函数中传递任何浮点值。
range 函数不适用于浮点值,因为根据 range 函数,浮点对象不能被解释为整数。因此,通常在范围函数中指定整数值。
x = range(10.0, 100.5)
for i in x:
print(i)**--------------------------------------------------------------------****TypeError Traceback (most recent call last)**[**<ipython-input-23-55e80efae649>**](/<ipython-input-23-55e80efae649>) **in <module>()
----> 1 x = range(10.0, 100.5)
2 for i in x:
3 print(i)****TypeError: 'float' object cannot be interpreted as an integer**
如果你需要解决它,你可以把它转换成一个整数,如下所示:
x = range(int(10.0), int(100.5))
for i in x:
print(i)**10
11
12
13
14
-
-
-
-
99**
为了支持这种情况,我对 StackOverflow 做了一些研究,然后我看到了一个问题,它被表述为“我想从 0 到 100 循环,但步长为 1/2 ”现在这不是一个简单的问题,因为上面的概念适用于此,所以你需要使用一些逻辑,现在我已经使用了一些我的逻辑来解决这个问题,如下所示:
x = range(0, 100 * 2)
for i in x:
print(i * 0.5)**0.0
0.5
1.0
1.5
2.0
-
-
-
99.5**
你可以自由地用你的逻辑解决上述问题,并在下面的评论区提供解决方案。
xrange 函数
这也是 python 中的一个内置函数,我认为它的工作方式与 range()相同,当我尝试执行它时,我得到了一个奇怪的错误:
x = xrange(1, 5)
for i in x:
print(i)**--------------------------------------------------------------------****NameError Traceback (most recent call last)**[**<ipython-input-30-969120b3b060>**](/<ipython-input-30-969120b3b060>) **in <module>()
----> 1 x = xrange(1, 5)
2 for i in x:
3 print(i)****NameError: name 'xrange' is not defined**
然后经过一番研究,我根据栈溢出得知 xrange 是 range 的增量版本。其中一个说 Python2 用的是 xrange(),Python3 用的是 range,所以你不用担心。
范围函数也可以用于列表
范围函数也可用于 python 列表。一种简单的方法如下所示:
names = [‘India’, ‘Canada’, ‘United States’, ‘United Kingdom’]
for i in range(1, len(names)):
print(names[i])**Canada
United States
United Kingdom**
使用范围函数增加和减少
我想现在你们应该知道该怎么做了。但无论如何,我会提供这个问题的解决方案。在这种情况下,您只需使用步进参数即可。
递增
x = range(1, 10, 2)
for i in x:
print(i)**1
3
5
7
9**
递减
x = range(10, 1, -2)
for i in x:
print(i)**10
8
6
4
2**
这就是你需要知道的关于 python 中 range 函数的全部内容,推荐你阅读 Python 的官方指南:
[## 内置函数- Python 3.8.0 文档
Python 解释器内置了许多始终可用的函数和类型。它们被列出…
docs.python.org](https://docs.python.org/3/library/functions.html#func-range)
感谢你们阅读这个简短的教程,我希望你们喜欢它,让我知道你的意见,如果你有任何疑问,评论区都是你的。
Python 正则表达式基础 5 分钟
对 Regex 世界的轶事介绍
当我开始网络抓取时,我经常会有奇怪字符的字符串,如\n\nnn 等等。我用替换功能把它去掉了。我构建了类似. str.replace(‘文本之墙’,‘’). str.replace(‘文本之墙’,’ ')的结构。结果是 1)可读性差,2)总是只有一个术语的单独解决方案,以及 3)非常低效的过程。所以我开始使用正则表达式来清理我的数据。在下面的文章中,我想和你分享我的发现和一些技巧。祝阅读愉快。
场景 1:从网络搜集的数据中提取信息
Python 提供了用于处理正则表达式的re
库。让我们导入它并创建一个字符串:
import re
line = "This is a phone number: (061) — 535555\. And this is another: 01–4657289, 9846012345"
re
有四种不同的功能:findall, search, split
和sub
。我们将从findall
开始学习基础知识。在我们的字符串中,显然有三个不同的电话号码,我们为我们的营销部门丢弃了它们(该字符串是来自 stackoverflow 的真实世界的例子)。我们的同事不需要整个字符串,而是需要一个列表,每个数字分开。第一步,我们尝试从字符串中提取每个数字:
foundNum = re.findall('\d', line)
print("The numbers found are: ", foundNum)
输出:
The numbers found are: ['0', '6', '1', '5', '3', '5', '5', '5', '5', '0', '1', '4', '6', '5', '7', '2', '8', '9', '9', '8', '4', '6', '0', '1', '2', '3', '4', '5']
如你所见,findall
有两个参数。第一项\d
是我们要找的表达式。在这种情况下,数字。第二项是包含我们感兴趣的模式的字符串。嗯,我们的市场部不能用这个打电话给任何客户,所以我们必须寻找不同的方法。
foundNum = re.findall('\(\d', line)
print("The numbers found are: ", foundNum)
输出:
The numbers found are: ['(0']
现在我们寻找括号和数字的组合。有一个匹配是第一个电话号码的开头。如果我们得出这个结果,营销部门将不会再向我们要求任何东西…好的,下一次尝试:
foundNum = re.findall("\(*\d*\d", line)
print("The phone numbers found are: ", foundNum)
输出:
The phone numbers found are: ['(061) - 535555', '01 - 4657289', '9846012345']
现在我们有了完美的解决方案。我们在表达式之间添加了一个列表,字符串必须以数字开头和结尾。术语[- \d()]
表示字符“-”、“”、数字或括号必须在数字之间。完美!我们的市场部对此会很高兴,可以打电话给我们的客户。快乐结局!
场景 2:清理和匿名化客户数据
我们在刮削项目中的出色表现之后,刚刚放了一天假。然而,在我们早上查看邮件后,我们注意到了另一个请求。我们销售部的同事有一些包含括号中表达式的字符串。出于隐私原因,括号内的术语必须删除。好了,我们已经学了很多,我们开始吧:
string_df = '500€ (Mr. Data) Product Category 1'
re.findall(r"\([a-zA-Z .]*\)", string_df)
输出:
['(Mr. Meier)']
好极了。这很容易。我们刚刚检查了一个以括号开始和结束的字符串,并包含了一个包含字母字符和一个点的列表。当我们开始写一封关于我们的好结果的邮件时,我们注意到我们不需要搜索这个术语。相反,我们必须删除这个表达式。我们后退一步,引入一个新函数sub
。re.sub
需要三个参数。第一个参数是我们要寻找的表达式,第二个参数是我们要用来替换旧参数的术语,最后一个参数是我们要使用的字符串:
re.sub(r"\([a-zA-Z .]*\)", "-XY-", string_df)
我们用表达式“-XY-”替换了这个名称。现在,销售部门可以将数据发送给我们的仪表板供应商。又一个幸福的结局。
场景 3:将字符串分成几部分
我们开始对正则表达式感到舒服。如果我们称自己为专家,那就有点言过其实了,但我们为每个问题都找到了解决方案,不是吗?在我们帮助了其他部门的同事后,我们专注于自己的工作。我们收到了新的数据进行探索性的数据分析。像往常一样,我们查看数据帧的第一行。第二列看起来很奇怪:
strange_cell = '48 Mr.Data 57'
根据我们以前的经验,我们得出第一个数字代表 Data 先生购买的单位数量。第二个数字告诉我们客户 id。我们需要在三个独立的栏目中提供这些信息,但是如何提供呢?Regex 提供了另一个名为split
的函数:
re.split(" ", strange_cell)
输出:
['48', 'Mr.Data', '57']
这正是我们要找的。有了这么多快乐的结局,你会认为你在看一部迪斯尼电影,对吗?
简短的课程
在漫长而成功的一天后,我们收到了市场部的另一封邮件,他们要求修改我们的第一个任务:他们只需要字符串中的第一个电话号码,因为这是业务电话号码:
line = "This is a phone number: (061) — 535555\. And this is another: 01–4657289, 9846012345"
使用searchall
功能,我们考虑每一场比赛。一个简单的解决方法是,我们只给出列表的第一个元素:
foundNum = re.findall(r"\(*\d[- \d()]*\d", line)[0]
print("The phone numbers found are: ", foundNum)
输出:
The phone numbers found are: (061) - 535555
另一个更好的解决方案是使用第四个正则表达式函数search
,它返回字符串中的第一个匹配:
foundNum = re.search(r"\(*\d[- \d()]*\d", line)
print("The phone numbers found are: ", foundNum)
输出:
The phone numbers found are: <re.Match object; span=(24, 38), match='(061) - 535555'>
结论
我希望你喜欢阅读并理解为什么Regex
对数据科学家如此重要。在数据清理和数据转换过程中,修改字符串是一种强有力的方法。如果你处理数据,你需要处理和转换字符串的技能。Regex
是完美的解决方案。对于不同表达的概述,我推荐以下页面:
正则表达式是构成搜索模式的一系列字符。正则表达式可以用来检查是否…
www.w3schools.com](https://www.w3schools.com/python/python_regex.asp) [## 正则表达式 HOWTO - Python 2.7.17 文档
该模块是在 Python 1.5 中添加的,提供了 Perl 风格的正则表达式模式。Python 的早期版本…
docs.python.org](https://docs.python.org/2/howto/regex.html)
如果您喜欢中级和高级数据科学,并且还没有注册,请随时使用我的推荐链接加入社区。
Python 风险管理:凯利标准
从最近金融市场调整的事件来看,我认为这将是一个谈论风险管理的有趣时刻。具体来说,我们将通过 Python 中的一个具体例子来回顾 Kelly 准则。首先,我们将讨论凯利标准的简要概述。接下来,我们来看一个简单的抛硬币的例子。最后,我们将举一个简单的例子,并将其应用于一个金融指数。
本文的数据收集自:https://www.investing.com/etfs/spdr-s-p-500-historical-data
简要凯利标准概述
约翰·凯利是美国电话电报公司·贝尔实验室的科学家。当时,凯利听说了职业赌徒,并对赌徒在面对不确定性时如何管理他们的资本感到好奇。有趣的是,他并不关心他们赚了多少钱,而是关心他们如何设置下注规模以获得最多的钱。像大多数成功的赌博故事一样,Kelly 应用信息论中的数学创建了 Kelly 准则(KC) [1]。从 KC 来看,如果一个赌徒知道自己赢和输的几率,她可以做出最好的赌注,从长远来看获得最多的钱。
凯利标准(KC)有两个主要部分:赢概率和赢/赔率。在数学公式形式中,那将是[2]:
但是 KC 的应用不仅仅是赌博。它适用于任何我们知道变量值的决策。
投资者如何应用凯利
在谷歌上快速搜索一下,你会发现很多人引用价值投资者的话,比如[3]:
我不能参与 50 或 75 件事情。这是一种诺亚方舟式的投资方式——你最终会得到一个动物园。我喜欢在一些事情上投入有意义的钱。—沃伦·巴菲特
当世界给智者提供机会时,他们会下大赌注。他们有胜算的时候会下大注。其他时候,他们不会。就是这么简单。—查理·芒格
这些大牌价值投资者大多不再直接应用 KC 了。当然,他们在他们的投资组合中使用集中下注,但是 KC 要求可重复下注以获得最佳回报[4]。这就是为什么如果你进一步挖掘,这些投资者大多会放弃 KC。不是因为 KC 不好,而是哲学上的投资差异。价值投资包括选择一些公司,并持有一段时间,使其达到公允价值。在计算公允价值时,大多数没有足够的可重复概率。这就是为什么大多数使用 KC 的投资者倾向于使用更多的量化策略来反映赌场的优势。
作弊抛硬币示例
背景介绍到此为止,让我们来看一些编码示例!现在,我们来看一下如何应用 KC,当你以 55%的优势掷硬币下注时(一枚公平的硬币有 50%的胜算)。对于我们的例子,让我们假设你赢了 1 美元或输了 1 美元,因为正面或反面的结果与风险的大小有关。换句话说,我们假设每注的 KC 或风险金额是 1 比 1。接下来的代码也是从用于金融的 Python 修改而来的 [5]。
#Import libraries
import math
import time
import numpy as np
import pandas as pd
import datetime as dt
import cufflinks as cf
from pylab import plt
np.random.seed(1) # For reproducibility
plt.style.use('seaborn') # I think this looks pretty
%matplotlib inline # To get out plots#Coin flip variable set up
p = 0.55 #Fixes the probability for heads.f = p - (1-p) #Calculates the optimal fraction according to the Kelly criterion.
f
f = 0.10
以上是最佳凯利标准最佳尺寸(f)。这意味着,对于 1 比 1 的回报和 55%的获胜机会,我们应该将总资本的 10%用于最大化我们的利润。
# Preparing our simulation of coin flips with variables
I = 50 #The number of series to be simulated.
n = 100 #The number of trials per series.
def run_simulation(f):
c = np.zeros((n, I)) #Instantiates an ndarray object to store the simulation results.
c[0] = 100 #Initializes the starting capital with 100.
for i in range(I): #Outer loop for the series simulations.
for t in range(1,n): #Inner loop for the series itself.
o = np.random.binomial(1, p) #Simulates the tossing of a coin.
if o > 0: #If 1, i.e., heads …
c[t, i] = (1+f) * c[t-1,i] #… then add the win to the capital.
else: #If 0, i.e., tails …
c[t, i] = (1-f) * c[t-1,i] #… then subtract the loss from the capital.
return c
c_1 = run_simulation(f) #Runs the simulation.
c_1.round(2) #Looking at a simulation
当运行模拟时,我有时喜欢检查数据看起来如何,只是为了看看没有什么疯狂的事情发生。我们将这些数据形象化,使其更容易理解。
plt.figure(figsize=(10,6))
plt.plot(c_1, 'b', lw=0.5) #Plots all 50 series.
plt.plot(c_1.mean(axis=1), 'r', lw=2.5); #Plots the average over all 50 series.
plt.title('50 Simulations of Rigged Coin Flips');
plt.xlabel('Number of trials');
plt.ylabel('$ Amount Won/Lost');
对于上面的图,蓝线代表我们运行的 50 次模拟抛硬币,红线代表所有模拟的平均值。有趣的是,即使我们以微弱的优势(55%的优势)获胜,也很少有我们仍然失败的情况。这可能就是为什么很多人在评估与机会有关的情况的盈利能力时会有问题。
除了始终用 10%的资金下注之外,其他下注规模/不同的 KC 值会发生什么?
c_2 = run_simulation(0.05) #Simulation with f = 0.05.
c_3 = run_simulation(0.25) #Simulation with f = 0.25.
c_4 = run_simulation(0.5) #Simulation with f = 0.5.plt.figure(figsize=(10, 6))
plt.plot(c_1.mean(axis=1), 'r', label='$f^*=0.1$')
plt.plot(c_2.mean(axis=1), 'b', label='$f=0.05$')
plt.plot(c_3.mean(axis=1), 'y', label='$f=0.25$')
plt.plot(c_4.mean(axis=1), 'm', label='$f=0.5$')
plt.legend(loc=0);
plt.title('Varied KC Simulations of Rigged Coin Flips');
plt.xlabel('Number of trials');
plt.ylabel('$ Amount Won/Lost');
从我们不同的 KC,我们可以看到回报(金额韩元)差异很大。具体来说,我们增加的 KC 越高,我们赢得更多钱的机会就越大,但风险也越大。到目前为止,我们的最佳值 0.10 确实看起来最好(持续盈利回报),而更高的值在回报方面有巨大的变化(f=0.25)甚至亏损(f=0.5)。
凯利去做间谍
现在让我们从简单的例子中走出来,把它推向现实世界。我们将把 KC 应用于标准普尔 500 股票指数。为了应用这些变化,我们的 KC 公式将如下所示[5]:
Mu ( ) =间谍平均收益
r =无风险率
sigma (σ ) =间谍方差
不用向上滚动数据链接,你可以在这里再找到:https://www.investing.com/etfs/spdr-s-p-500-historical-data【6】。
#Loading SPY data
data = pd.read_csv('SPY Historical Data.csv', index_col=0, parse_dates=True)#Light Feature Engineering on Returns
data['Change %'] = data['Change %'].map(lambda x: x.rstrip('%')).astype(float) / 100
data.dropna(inplace=True)data.tail()
只是检查数据,看看我们的功能工程是否有效。来自 Investing.com 的数据通常有一个%符号,Python 倾向于将其作为一个对象而不是一个数字。
mu = data['Change %'].mean() * 252 #Calculates the annualized return.
sigma = (data['Change %'].std() * 252 ** 0.5) #Calculates the annualized volatility.
r = 0.0179 #1 year treasury ratef = (mu - r) / sigma ** 2 #Calculates the optimal Kelly fraction to be invested in the strategy.
f
f = 4.2
根据我们的计算,KC 值是 4.2,这意味着我们应该为间谍投资的每 1 美元下注 4.2 倍。对于那些对金融更熟悉的人来说,这意味着我们应该利用 4.2 倍的交易来最大化我们的预期回报。直觉上,对我来说听起来有点高,但是让我们像以前一样运行一些模拟。
equs = [] # preallocating space for our simulationsdef kelly_strategy(f):
global equs
equ = 'equity_{:.2f}'.format(f)
equs.append(equ)
cap = 'capital_{:.2f}'.format(f)
data[equ] = 1 #Generates a new column for equity and sets the initial value to 1.
data[cap] = data[equ] * f #Generates a new column for capital and sets the initial value to 1·f∗.
for i, t in enumerate(data.index[1:]):
t_1 = data.index[i] #Picks the right DatetimeIndex value for the previous values.
data.loc[t, cap] = data[cap].loc[t_1] * math.exp(data['Change %'].loc[t])
data.loc[t, equ] = data[cap].loc[t] - data[cap].loc[t_1] + data[equ].loc[t_1]
data.loc[t, cap] = data[equ].loc[t] * f
kelly_strategy(f * 0.5) # Values for 1/2 KC
kelly_strategy(f * 0.66) # Values for 2/3 KC
kelly_strategy(f) # Values for optimal KCax = data['Change %'].cumsum().apply(np.exp).plot(legend=True,figsize=(10, 6))
data[equs].plot(ax=ax, legend=True);
plt.title('Varied KC Values on SPY, Starting from $1');
plt.xlabel('Years');
plt.ylabel('$ Return')
就像我们掷硬币的例子一样,KC 值越高,波动性越大。4.2 的最佳金额在 2019 年初前后损失了超过 50%的价值。这对于大多数人来说是相当可怕的,这就是为什么应用 KC 的从业者通常应用 KC 的一半(equity_2.10 from out plot)。
结论
我们今天走了相当多的路。我们回顾了凯利标准(KC)的简史,以及投资者如何应用这个公式。然后我们用一个简单的作弊抛硬币的例子来最大化我们的回报。最后,我们将从抛硬币的例子中学到的知识应用到标准普尔 500 股票指数中。从我们的小模拟中,我们了解到,即使 KC 可能推荐一个高值,有时我们也会采用一个降低的 KC 值来避免不必要的波动。没有多少人能忍受 50%的损失(最大的损失金额),不要让我开始承受经历一次的精神压力!所以采取战略解决方案,通过降低 KC 来获得更多的安心。
免责声明:本文陈述的所有内容都是我个人的观点,不代表任何雇主。投资带有严重的风险,在采取任何投资行动之前,请咨询您的投资顾问。此外,这个帖子包含附属链接。
参考
[1] Finbox,Investing With Kelly (2018),https://www . value walk . com/2018/04/Investing-With-the-Kelly-criterion-model/
[2] J. Kuepper,利用凯利准则进行资产配置和资金管理(2019),【https://www.investopedia.com/articles/trading/04/091504.asp
[3] OSV,将凯利标准应用于投资和您的投资组合规模(2014),https://www . oldschoolvalue . com/blog/Investing-strategy/Kelly-Criterion-Investing-Portfolio-Sizing/
[4] P. Lindmark,用凯利标准投资(2007 年),https://www . guru focus . com/news/4883/用凯利标准投资
[5] Y. Hiplisch,Python for Finance:掌握数据驱动的金融(2018),奥赖利媒体https://amzn.to/2KuHPRG
[6]Investing.com,间谍 500 史料,https://www.investing.com/etfs/spdr-s-p-500-historical-data
Python Seaborn 使用 reticulate 在 R 中绘图
我认为没有人会质疑ggplot2
有多神奇。但是在 Python 的现代数据可视化库Seaborn
中有几个我很欣赏的情节。这不仅仅是因为它能产生高质量的可视化效果,还因为它的构建是多么的容易和简单。那两个地块是heatmap
和pairplot
。我总是想念他们,但我想不会了。
如果我告诉您,您现在可以使用 RStudio 在 R 中构建 Seaborn 热图和 pairplot,会怎么样?在这篇文章中,我们将看到如何制作像 Pairplot 和 Heatmap 这样的 Seaborn 可视化工具,就此而言,r。
网状的
这里的圣杯是最近推出的 R 包reticulate
,由 RStudio 开发。
关于套餐:
reticulate 包为 Python 和 r 之间的互操作性提供了一套全面的工具。
- 以多种方式从 R 调用 Python,包括 R Markdown、获取 Python 脚本、导入 Python 模块以及在 R 会话中交互使用 Python。
- R 和 Python 对象之间的转换(例如,R 和 Pandas 数据框之间,或者 R 矩阵和 NumPy 数组之间)。
- 灵活绑定到不同版本的 Python,包括虚拟环境和 Conda 环境。
Reticulate 在 R 会话中嵌入了一个 Python 会话,实现了无缝、高性能的互操作性。
安装和加载 R 包
reticulate
在曲柄上可用,并可按以下代码安装:
install.packages('reticulate')
让我们将 R 包加载到当前的 R 会话中(就像加载其他 R 包一样):
#loading required R libraries
library(reticulate) #the superpower bridges python and R
初始设置
记住,要访问这个包,您的机器中需要有 Python。所以请确保您已经安装了 Python 以及所需的包,并且在PATH
上可用,默认情况下,reticulate 使用路径上的 Python 版本。如果您的计算机上有多个 Python 版本,您可以使用以下代码指示使用哪个版本的 Python for reticulate:
#specifying which version of python to use
use_python('C:\\PROGRA~1\\Python35\\python.exe')
加载 Python 库
import()
函数帮助将指定的 Python 库导入当前 R 会话。记住,指定的 Python 库必须已经安装在机器上。
#importing required Python libraries/modules
sns <- import('seaborn')
plt <- import('matplotlib.pyplot')
pd <- import('pandas')
代码结构
这段代码做两件事:
R 中的 Seaborn 热图
#using R's inbuilt AirPassengers dataset
df <- datasets::AirPassengers
#converting Time-Series object into an R Dataframe
#Thx: [https://stackoverflow.com/questions/5331901/transforming-a-time-series-into-a-data-frame-and-back](https://stackoverflow.com/questions/5331901/transforming-a-time-series-into-a-data-frame-and-back)
df1 <- data.frame(tapply(df, list(year = floor(time(df)), month = month.abb[cycle(df)]), c))
df1 <- df1[month.abb]
#building a heatmap using seaborn
#please note the function r_to_py() that converts R object into a python
sns$heatmap(r_to_py(df1), fmt="g", cmap ='viridis')
#display the plot
plt$show()
给出了这个图:
这真是一张漂亮的热图。为了理解那里发生了什么,我们采用了 AirPassengers 数据集,这是一个时间序列格式的 R 对象。这被转换成数据帧,然后输入到 seaborn 的热图功能,以绘制热图。这里需要注意一些事情:
- 在载入 python 库的对象后使用
$
符号访问 Python 包的函数。这与使用$
访问数据帧的一列非常相似。 r_to_py()
是一个用来把 R 对象转换成 Python 对象的函数。在这种情况下,R 数据帧被转换为 Python Pandas 数据帧,这是热图函数绘制热图的理想对象类型。
R 中的 Seaborn 配对图
#building a seaborn pairplot using pairplot()
sns$pairplot(r_to_py(iris), hue = 'Species')
#display the plot
plt$show()
给出了这个图:
这是理解给定数据集中成对关系的一个很好的图。
结论
因此,只需很少的编码和配置,我们就能在 R 中使用 Python Seaborn 很好地可视化给定的数据集,并绘制出热图和 Pairplot。虽然这篇文章可能已经非常具体地描述了这两个图,但是从这篇文章中可以推断出的更大的想法是理解使用reticulate
包将 Python 代码集成到 R 代码中是多么简单和容易。这里使用的完整代码可以在我的 github 上获得。r 是任何形式的数据可视化的神奇工具,要了解更多请查看这个。
参考
Python 字符串从零开始!!!
让我们了解一下 python 中字符串的基础知识。
Credits: GangBoard
字符串是一系列字符,可以存储为常量或不同的变量。字符串被视为一种数据类型。通常,程序员必须用引号将字符串括起来,以便将数据识别为字符串,而不是数字或变量名。下面是一些日常最常用的字符串方法,也是最常被问到的面试问题之一。此外,代码可以在我的 GitHub 页面上找到。
比如用 python 声明一个字符串:
**# Declaring a string variable** string = “This is a python tutorial”
print(string)**This is a python tutorial**print(type(string))**<class 'str'>**
1。使用字符串对 python 中的序列进行转义
在 Python 字符串中,反斜杠“”是一个特殊字符,也称为“转义字符。它用于表示某些空白字符:" \t “是一个制表符,” \n “是一个新行,” \r "是一个回车符。最后,“”可以用来转义本身:“ ** ”是字面上的反斜杠字符。来源 Python 教程。
**# THis is an escape sequence.** string = “This is a \”Google Colab\” python notebook”print(string)**This is a "Google Colab" python notebook**
2。通过索引访问字符串
字符串可以通过它们的索引来访问,以便获得值。要做到这一点,你所要做的就是把数字(索引值)和字符串的名字放在一对方括号内。
string = “Python”print(string[2])**t**print(string[5])**n**
3。切一根绳子
分割字符串有助于从字符串中获取一组字符。当我们想要访问字符串中的一组特定字符时,这非常有用。下面是一些有用的切片变体。
string = “programming”
string**'programming'**
获取字符串中的一个字符
print(string[0:1])**p**
从字符串中获取前三个字符
print(string[0:3])**pro**
从字符串中获取前三个字符(替换)
print(string[:3])**pro**
从字符串中获取最后三个字符
print(string[-3:])**ing**
获取所有字符,但不包括字符串中的前三个字符
print(string[3:])**gramming**
获取所有字符,但不包括字符串的后三个字符
print(string[:-3])**programm**
反转给定字符串中的所有字符
print(string[::-1])**gnimmargorp**
打印字符串中所有字符的替代方法
print(string[::])**programming**
4。拆分字符串
有时拆分字符串是一个方便的选择,因为这是将字符串转换成列表的最简单的方法之一。我知道我没有提到列表,但是请记住,split 将字符串转换为列表。你可以找到我写的关于 python 列表的材料,它可以为掌握 Python 列表提供足够的思路:
让我们从基础到高级理解 Python 列表。
towardsdatascience.com](/python-lists-from-scratch-4b958eb956fc)
String = “Computer Programming”
String**‘Computer Programming’**type(String)**str**list = String.split()
list**['Computer', 'Programming']**type(list)**list**
5。替换字符串
python 中的 Replace 函数是可以应用于字符串的最好的函数之一。例如,下面显示的是一个字符串“Money ”,我们需要替换美元和逗号,这可以如下所示完成。
Money = ‘$113,678’
print(Money)
print(“===========================”)
print(type(Money))**$113,678
===========================
<class ‘str’>**Money = Money.replace(‘$’, ‘’)
Money**‘113,678’**Money = Money.replace(‘,’, ‘’)
Money**‘113678’**Money = int(Money)
print(Money)
print(“===========================”)
print(type(Money))**113678
===========================
<class ‘int’>**
6。加入
连接函数是 python 用来按照指定的模式连接字符串的。
String = “Python Programming is fun”
String**‘Python Programming is fun’**String = “ “.join(String)
String**‘P y t h o n P r o g r a m m i n g i s f u n’**
7.大写
capitalize 函数将单词或字符串中的第一个字符大写。
string = “programming”
string**‘programming’**string = string.capitalize()
string**‘Programming’**
8.中心
center 方法返回用指定字符填充的字符串。
string = “python”
string**‘python’**print(string.center(15, ‘*’))*******python******
9.发现
find 方法返回给定子串位置的索引。如果找不到该值,则返回-1。
string = “programming”
string**‘programming’**print(string.find(‘p’))**0**print(string.find(‘t’))**-1**
10.剥夺
strip 函数去除字符串开头和结尾的空格。
string = “ programming is easy “
string**‘ programming is easy ‘**print(string.strip())**programming is easy**
因此,以上是 Python 中非常重要的字符串技术或函数。一些例子是从 Python 字符串中引用的。我用一种简单的方式写了这篇教程,这样每个人都可以理解和掌握 Python 中字符串的概念,而不需要以前的编程知识或经验。如果你们对代码有什么疑问,评论区就是你们的了。
谢谢你
Python 的技巧和诀窍,你还没有看过
注:这最初发布在martinheinz . dev
关于 Python 中的许多很酷的特性,比如变量解包、部分函数、枚举可迭代对象,已经有很多文章,但是对于 Python 来说,还有更多的东西要讨论,所以在这里我将尝试展示一些我知道并使用的特性,这些特性我还没有在其他地方提到过。所以我们开始吧。
净化字符串输入
净化用户输入的问题几乎存在于你编写的每一个程序中。通常,将字符转换为小写或大写就足够了,有时您可以使用 Regex 来完成这项工作,但是对于复杂的情况,可能有更好的方法:
在此示例中,您可以看到空白字符“\n”和“\t”已被替换为单个空格,并且“\r”已被完全删除。这是一个简单的例子,但是我们可以更进一步,使用unicodedata
包和它的combining()
函数生成大的重映射表,来生成和映射我们可以用来从字符串中删除所有重音符号的表。
获取迭代器的切片
如果你尝试获取迭代器的一部分,你会得到一个TypeError
,声明生成器对象是不可下标的,但是有一个简单的解决方法:
使用itertools.islice
我们可以创建一个islice
对象,它是一个迭代器,产生想要的项目。不过需要注意的是,这将消耗 slice 开始之前的所有生成器项,以及我们的islice
对象中的所有项。
跳过 Iterable 的开头
有时你不得不处理那些你知道以可变数量的不需要的行开始的文件,比如注释。itertools
再次提供了简单的解决方案:
该代码片段只在初始注释部分后生成几行。如果我们只想丢弃 iterable 开头的条目(本例中是行),而不知道有多少条目,这种方法会很有用。
只有关键字参数的函数(kwargs)
创建只接受关键字参数函数会有所帮助,以便在使用这样的函数时提供(强制)更大的清晰度:
如你所见,这可以通过在关键字参数前放置单个*
参数来轻松解决。如果我们把位置参数放在*
参数之前,显然会有位置参数。
创建支持with
语句的对象
我们都知道如何使用with
语句打开文件或者获取锁,但是我们真的能实现我们自己的吗?是的,我们可以使用__enter__
和__exit__
方法实现上下文管理器协议:
这是在 Python 中实现上下文管理的最常见方法,但是还有更简单的方法:
上面的代码片段使用contextmanager
manager decorator 实现了内容管理协议。进入with
块时执行tag
功能的第一部分(在yield
之前),然后执行该块,最后执行tag
功能的剩余部分。
使用__slots__
节省内存
如果你曾经写过一个程序,它创建了某个类的大量实例,你可能会注意到你的程序突然需要大量的内存。这是因为 Python 使用字典来表示类的实例的属性,这使得它很快,但不是非常有效的内存,这通常不是问题。然而,如果它成为你的程序的一个问题,你可以尝试使用__slots__
:
这里发生的情况是,当我们定义__slots__
属性时,Python 使用小的固定大小的属性数组而不是字典,这大大减少了每个实例所需的内存。使用__slots__
也有一些缺点——我们不能声明任何新的属性,并且我们被限制在__slots__
上使用。同样,带有__slots__
的类不能使用多重继承。
限制 CPU 和内存的使用
如果您不想优化程序内存或 CPU 的使用,而是想直接将其限制在某个硬数字,那么 Python 也有一个库:
在这里,我们可以看到设置最大 CPU 运行时间和最大内存使用限制的两个选项。对于 CPU 限制,我们首先获得特定资源软限制和硬限制(RLIMIT_CPU
),然后使用参数指定的秒数和先前检索的硬限制来设置它。最后,如果 CPU 时间超时,我们注册导致系统退出的信号。至于内存,我们再次检索软限制和硬限制,并使用带有大小参数和检索到的硬限制的setrlimit
进行设置。
控制什么可以导入,什么不可以导入
有些语言有非常明显的导出成员(变量、方法、接口)的机制,比如 Golang,只导出以大写字母开头的成员。另一方面,在 Python 中,一切都是导出的,除非我们使用__all__
:
使用上面的代码片段,我们可以限制使用from some_module import *
时可以导入的内容。对于这个具体的例子,通配符导入与仅导入bar
。此外,我们可以将__all__
留空,当使用通配符导入从该模块导入时,不会导出任何内容,从而导致AttributeError
。
比较运算符最简单的方法
考虑到有相当多的比较操作符——__lt__ , __le__ , __gt__ ,
或__ge__
,为一个类实现所有的比较操作符可能会很烦人。但是如果有更简单的方法呢?functools.total_ordering
来救援:
这实际上是如何工作的?total_ordering
decorator 用于简化我们的类实现实例排序的过程。只需要定义__lt__
和__eq__
,这是映射剩余操作所需的最低要求,这是装饰者的工作——它为我们填补了空白。
结论
在日常 Python 编程中,并非所有这些特性都是必不可少的和有用的,但其中一些有时可能会派上用场,它们还可能会简化任务,否则实现起来会非常冗长和烦人。我还想指出的是,所有这些特性都是 Python 标准库的一部分,而其中一些在我看来就像是标准库中非常非标准的东西,所以每当你决定用 Python 实现某个东西时,首先要在标准库中寻找它,如果你找不到它,那么你可能找得不够仔细(如果它真的不在那里,那么它肯定在某个第三方库中)。🙂
您还没有看过的 Python 技巧和诀窍,第 2 部分
注意:这最初发布在martinheinz . dev
几周前,我发表了一篇文章(此处为)关于一些不太为人所知的 Python 特性,很多人似乎都喜欢它,所以这里有另一轮 Python 特性,希望你还没有看到。
使用slice
功能命名切片
使用大量硬编码的索引值很快会导致维护和可读性方面的混乱。一种选择是对所有索引值使用常量,但我们可以做得更好:
在这个例子中,我们可以看到我们可以避免神秘的索引,首先使用slice
函数命名它们,然后在切掉字符串的一部分时使用它们。您还可以使用切片对象的属性.start
、.stop
和.step
来获得更多关于切片对象的信息。
许多命令行工具或脚本需要用户名和密码才能操作。因此,如果您碰巧编写了这样的程序,您可能会发现getpass
模块很有用:
这个非常简单的包允许您提示用户输入密码,并通过提取当前用户的登录名来获取他们的用户名。请注意,不是每个系统都支持隐藏密码。Python 会试图警告你这一点,所以只需在命令行中阅读警告。
现在,对于 Python 标准库的一个更难理解的特性。如果您发现自己需要使用类似于Levenshtein distancePython 和difflib
的工具来查找类似于某个输入字符串的单词,您会得到支持。
difflib.get_close_matches
找到最佳的*【足够好】*匹配。这里,第一个参数与第二个参数相匹配。我们还可以提供可选参数n
,它指定要返回的最大匹配数。可以设置另一个可用的关键字参数cutoff
(默认为 0.6)来改变匹配字符串得分的阈值。
如果你必须用 Python 做一些网络工作,你可能会发现ipaddress
模块非常有用。一个用例是从 CIDR 生成 ip 地址列表(无类域间路由):
另一个很好的特性是 ip 地址的网络成员检查:
还有很多更有趣的特性我就不赘述了,因为你可以在这里找到那些。但是请注意,在ipaddress
模块和其他网络相关模块之间只有有限的互操作性。例如,您不能使用IPv4Network
的实例作为地址字符串——它们需要首先使用str
进行转换。
如果你是一个拒绝使用 IDE 并且用 Vim 或 Emacs 编码的人,那么你可能会遇到这样一种情况,在 IDE 中使用调试器是很有用的。你知道吗?你有一个——用python3.8 -i
运行你的程序——-i
会在你的程序终止时启动交互式 shell,从那里你可以探索所有变量并调用函数。很好,但是实际的调试器(pdb
)怎么样?
让我们使用下面的程序(script.py
):
用python3.8 -i script.py
运行脚本
我们看到了崩溃的位置,现在让我们设置一个断点:
现在再运行一次:
大多数情况下,打印语句和回溯对于调试来说已经足够了,但有时,您需要开始探索一下,以了解程序内部发生了什么。在这些情况下,您可以设置断点,当您运行程序时,执行将在断点处停止,您可以检查您的程序,例如,列出函数参数、计算表达式、列出变量或如上所示单步执行。pdb
是全功能的 python shell,所以你可以执行任何文学上的东西,但是你需要一些调试器命令,你可以在这里找到
一个在编程语言中很常见,但在 Python 中不常见的特性是函数重载。即使不能重载普通函数,也可以使用类方法重载构造函数:
你可能会倾向于将备选构造函数的所有逻辑放到__init__
中,并使用*args
、**kwargs
和一堆if
语句来解决它,而不是使用类方法。这可能行得通,但可能会变得难以阅读和维护。因此,我建议在__init__
中加入很少的逻辑,并在不同的方法/构造函数中执行所有的操作。通过这种方式,对于类的维护者和用户来说,你将得到干净清晰的代码。
您是否曾经编写过执行昂贵的 I/O 操作的函数,或者可以从缓存(内存化)结果中获益的相当慢的递归函数?如果你这样做了,那么使用来自functools
的lru_cache
有一个简单的解决方案:
在本例中,我们正在缓存 GET 请求(最多 32 个缓存结果)。您还可以看到,我们可以使用cache_info
方法检查我们函数的缓存信息。装饰器还提供了一个使缓存结果无效的clear_cache
方法。我还想指出,这不应该用于有副作用的函数或每次调用都会创建可变对象的函数。
在列表中找到最常见的项目是一项非常普通的任务,你可以使用for
循环和字典(map)来完成,但这将是浪费时间,因为在collections
模块中有Counter
类:
在幕后,Counter
只是一个将条目映射到出现次数的字典,因此您可以像使用普通的dict
一样使用它:
除此之外,您还可以使用update(more_words)
方法轻松地添加更多的元素到计数器中。Counter
的另一个很酷的特性是,你可以使用数学运算(加法和减法)来组合和减去Counter
的实例。
我认为,如果你正在使用 Python,这次我在这里分享的大多数技巧几乎每天都有用,所以我希望它们能派上用场。此外,如果你对这些 Python 技巧和诀窍有任何想法,或者如果你知道解决上述问题的任何更好的方法,请告诉我!🙂
初级数据科学家的 Python 工具
使用这些库使数据科学家的生活变得非常容易
Python 拥有适用于数据科学项目生命周期所有阶段的工具。任何数据科学项目固有地包含以下 3 个阶段。
Photo by Florian Klauer on Unsplash
- 数据收集
- 数据建模
- 数据可视化
Python 为这三个阶段提供了非常简洁的工具。
数据收集
1)美汤
当数据收集涉及到从网上抓取数据时,python 提供了一个名为 beautifulsoup 的库。
**from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc, 'html.parser')**
这个库解析一个网页并整齐地存储它的内容。比如,它会单独存储标题。它还将单独存储所有的标签,这将为您提供包含在页面中的非常整洁的 URL 列表。
作为一个例子,让我们看一个关于爱丽丝漫游奇境记的简单网页。
Webpage screenshot
显然,我们可以看到一些 html 元素,我们可以抓取。
- 标题——睡鼠的故事
- 页面文本
- 超链接——埃尔希、拉西和蒂莉。
Soup 使得提取这些信息变得很容易
**soup.title**
*# <title>The Dormouse's story</title>***soup.title.string**
*# u'The Dormouse's story'***soup.p**
*# <p class="title"><b>The Dormouse's story</b></p>***for link in soup.find_all('a'):
print(link.get('href'))**
*#* [*http://example.com/elsie*](http://example.com/elsie) *#* [*http://example.com/lacie*](http://example.com/lacie) *#* [*http://example.com/tillie*](http://example.com/tillie)**print(soup.get_text())** *# The Dormouse's story
#
# Once upon a time there were three little sisters; and their names were
# Elsie,
# Lacie and
# Tillie;
# and they lived at the bottom of a well.
#
# ...*
对于从 HTML 和 XML 文件中提取数据来说,这是一个极好的工具。它提供了导航、搜索和修改解析树的惯用方法。它通常可以为程序员节省数小时甚至数天的工作时间。
2) Wget
下载数据,尤其是从网上下载数据,是数据科学家的重要任务之一。Wget 是一个免费的实用程序,用于从网络上非交互式下载文件。因为它是非交互式的,所以即使用户没有登录,它也可以在后台工作。它支持 HTTP、HTTPS 和 FTP 协议,以及通过 HTTP 代理的检索。因此,下次你想下载一个网站或一个页面上的所有图片时, wget 随时为你提供帮助。
>>> **import wget**
>>> **url = '**[**www.futurecrew.com/skaven/song_files/mp3/razorback.mp3'**](http://www.futurecrew.com/skaven/song_files/mp3/razorback.mp3')
>>> **filename = wget.download(url)**
*100% [................................................] 3841532 / 3841532* >>> **filename**
*'razorback.mp3'*
3)数据 API
除了你需要抓取或下载数据的工具之外,你还需要实际的数据。这就是数据 API 发挥作用的地方。python 中有许多 API 可以让您免费下载数据,例如 Alpha Vantage 提供全球股票、外汇和加密货币的实时和历史数据。他们有长达 20 年的数据。
例如,使用 alpha vantage APIs,我们可以提取比特币每日价值的数据并绘制出来
from **alpha_vantage.cryptocurrencies** import **CryptoCurrencies**
import **matplotlib.pyplot** as **plt**
**cc = CryptoCurrencies(key='YOUR_API_KEY',output_format='pandas')
data, meta_data = cc.get_digital_currency_daily(symbol='BTC', market='USD')
data['1a. open (USD)'].plot()
plt.tight_layout()
plt.title('Alpha Vantage Example - daily value for bitcoin (BTC) in US Dollars')
plt.show()**
Plotted Image
其他类似的 API 示例有
- 开放通知 API — NASA 和国际空间站数据
- 汇率 API —欧洲中央银行发布的当前和历史外汇汇率
A few APIs for data collection
数据建模
正如本文中提到的,数据清理或平衡是数据建模之前的一个重要步骤。
1)不平衡学习
Imabalanced-learn 就是这样一个平衡数据集的工具。当一个类或类别的数据比其他类别的数据具有不成比例的大样本时,数据集是不平衡的。这可能会给分类算法带来巨大的问题,分类算法最终可能会偏向拥有更多数据的类。
[## 亚马逊废除了显示对女性有偏见的秘密人工智能招聘工具
(路透社)-Amazon.com 公司的机器学习专家发现了一个大问题:他们的新…
www.reuters.com](https://www.reuters.com/article/us-amazon-com-jobs-automation-insight-idUSKCN1MK08G)
例如,该库中名为 Tomek-Links 的命令有助于平衡数据集。
from **imblearn.under_sampling** import **TomekLinks **
tl = **TomekLinks**(return_indices=True, ratio='majority')
X_tl, y_tl, id_tl = **tl.fit_sample**(X, y)
Balancing an imabalanced data set
2)冰冷的生态系统——NumPy
Image by Ty Shaikh
实际的数据处理或建模通过 python 的 scipy 堆栈进行。Python 的 SciPy Stack 是专门为 python 中的科学计算设计的软件集合。nScipy secosystem 包含了许多有用的库,但是 Numpy 无疑是其中最强大的工具。
最基本的包 NumPy 代表数值 Python,科学计算栈就是围绕它构建的。它为矩阵运算提供了大量有用的特性。如果有人使用过 MATLAB,他们会立即意识到 NumPy 不仅和 MATLAB 一样强大,而且在操作上也非常相似。
3)熊猫
Pandas 是一个提供数据结构来处理和操作数据的库。称为 dataframe 的二维结构是最流行的一种。
熊猫是数据争论的完美工具。它旨在实现快速简单的数据操作、聚合和可视化。
Example of a DataFrame — Shanelynn
数据可视化
1) Matplotlib
SciPy 生态系统中的另一个软件包是 Matplotlib,它是为轻松生成简单而强大的可视化而定制的。这是一个 2D 绘图库,以各种硬拷贝格式生成出版物质量数字
Matplotlib 输出的一些示例
import numpy as np
import matplotlib.pyplot as pltN = 5
menMeans = (20, 35, 30, 35, 27)
womenMeans = (25, 32, 34, 20, 25)
menStd = (2, 3, 4, 1, 2)
womenStd = (3, 5, 2, 3, 3)
ind = np.arange(N) # the x locations for the groups
width = 0.35 # the width of the bars: can also be len(x) sequencep1 = plt.bar(ind, menMeans, width, yerr=menStd)
p2 = plt.bar(ind, womenMeans, width,
bottom=menMeans, yerr=womenStd)plt.ylabel('Scores')
plt.title('Scores by group and gender')
plt.xticks(ind, ('G1', 'G2', 'G3', 'G4', 'G5'))
plt.yticks(np.arange(0, 81, 10))
plt.legend((p1[0], p2[0]), ('Men', 'Women'))plt.show()
Bar Plot
其他几个例子
Taken from Matplotlib Docs
海洋生物
Seaborn 是一个基于 matplotlib 的 Python 数据可视化库。它主要为绘制有吸引力的和信息丰富的统计图形提供高级接口。它主要侧重于可视化,如热图
Seaborn docs
3)运动速度
MoviePy 是一个用于视频编辑的 Python 库,包括剪切、拼接、标题插入、视频合成、视频处理和自定义效果的创建。它可以读写所有常见的音频和视频格式,包括 GIF。
https://zulko.github.io/moviepy/gallery.html
奖金自然语言处理工具— FuzzyWuzzy
这个有趣的发声工具在字符串匹配方面是一个非常有用的库。人们可以快速实现诸如字符串比较比率、令牌比率等操作。
>>> **fuzz.ratio("this is a test", "this is a test!")**
97
>>> **fuzz.partial_ratio("this is a test", "this is a test!")**
100
>>> **fuzz.ratio("fuzzy wuzzy was a bear", "wuzzy fuzzy was a bear")**
91
>>> **fuzz.token_sort_ratio("fuzzy wuzzy was a bear", "wuzzy fuzzy was a bear")**
100
Python 拥有大量的信息和工具来执行数据科学项目。探索永远不会太迟!
Python 窍门 101,每个新程序员都应该知道的。
A pretty picture to catch your eye.
Python 比以往任何时候都更受欢迎,人们每天都在证明 Python 是一种非常强大且易于掌握的语言。
我从事 Python 编程已经有几年了,最近 6 个月是专业的,以下是我希望在刚开始时就知道的一些事情:
- 字符串操作
- 列表理解
- λ&map()
- if、elif 和 else 条件一行程序
- zip()
# 1: 琴弦操纵
Pun definitely intended
Python 非常擅长使用数学运算符+
和*
来决定如何处理字符串:
>>> my_string = "Hi Medium..!"
>>> print(my_string * 2)
**Hi Medium..!Hi Medium..!**>>> print(my_string + " I love Python" * 2)
**Hi Medium..! I love Python I love Python**
我们也可以很容易地反转一个字符串,使用[::-1]
,这不仅限于字符串!:
>>> print(my_string[::-1])
**!..muideM iH**>>> my_list = [1,2,3,4,5]
>>> print(my_list[::-1])
**[5, 4, 3, 2, 1]**
单词列表呢?我们可以做一个尤达翻译机!:
>>> word_list = ["awesome", "is", "this"]
>>> print(' '.join(word_list[::-1]) + '!')
**this is awesome!**
上面我们使用了.join()
方法,用' '
(空格)连接反转列表中的所有元素,并添加一个感叹号。
# 2:列出理解
哦,孩子,一旦我知道了这些,我的整个世界都变了(不是真的,但足够接近了)。这是对列表进行快速操作的一种非常强大、直观和可读的方式。
假设我们有一个随机函数,将一个数平方并加上 5:
>>> def stupid_func(x):
>>> return x**2 + 5
现在,假设我们想将这个函数应用于列表中的所有奇数,如果您不知道列表的理解,这可能是您要做的:
>>> my_list = [1, 2, 3, 4, 5]
>>> new_list = []
>>> for x in my_list:
>>> if x % 2 != 0:
>>> new_list.append(stupid_func(x))
>>> print(new_list)
**[6, 14, 30]**
但是有一个更简单的方法!:
>>> my_list = [1, 2, 3, 4, 5]
>>> print([stupid_func(x) for x in my_list if x % 2 != 0])
**[6, 14, 30]**
List comprehensions 与语法[ expression **for** item **in** list ]
一起工作,如果你想用一个额外的布尔条件,比如上面的“奇数”条件:[ expression **for** item **in** list **if** conditional ]
这与:
>>> **for** item **in** list:
>>> **if** conditional:
>>> expression
非常酷!尽管如此,我们仍然可以做得更好,因为我们并不真的需要那个“stupid_func
”:
>>> print([x ** 2 + 5 for x in my_list if x % 2 != 0])
**[6, 14, 30]**
嘣!
# 3: Lambda & Map
Crazy paint skills coming in from the right
希腊字母的第 11 个
Lambda 有点奇怪,但就像这个列表中的其他东西一样,一旦你明白了,它真的很强大而且很直观。
基本上,Lambda 函数是一个小型的匿名函数。为什么匿名?因为 Lambdas 最常用于执行不需要像def my_function()
这样的正式函数定义的小/简单操作。
让我们以上面的例子为例,将一个数平方并加 5。上面我们用def stupid_func(x)
做了一个正式的函数定义,现在让我们用一个 lambda 函数重新创建它:
>>> stupid_func = (lambda x : x ** 2 + 5)
>>> print([stupid_func(1), stupid_func(3), stupid_func(5)])
**[6, 14, 30]**
那么为什么要使用这种奇怪的语法呢?当你想在不定义实际函数的情况下执行一些简单的操作时,这就变得很有用了。以数字列表为例,我们如何在 Python 中对这样的列表进行排序?一种方法是使用sorted()
方法:
>>> my_list = [2, 1, 0, -1, -2]
>>> print(sorted(my_list))
**[-2, -1, 0, 1, 2]**
这样做了,但是假设我们想要按最小平方数排序,我们可以使用 lambda 函数来定义键,这是sorted()
方法用来确定如何排序的。
>>> print(sorted(my_list, **key** = lambda x : x ** 2))
**[0, -1, 1, -2, 2]**
地图
Map 是一个简单的函数,用于将函数应用于一些元素序列,如列表。假设我们必须列出一个列表中的每个元素与另一个列表中相应的元素相乘的位置,我们如何做呢?使用 lambda 函数和映射!:
>>> print(list(map(lambda x, y : x * y, [1, 2, 3], [4, 5, 6])))
**[4, 10, 18]**
与这个怪物相比,这是简单而优雅的:
>>> x, y = [1, 2, 3], [4, 5, 6]
>>> z = []
>>> for i in range(len(x)):
>>> z.append(x[i] * y[i])
>>> print(z)
**[4, 10, 18]**
# 4: if、elif 和 else 条件一行程序
在代码的某个地方,您可能会看到这样的内容:
>>> x = int(input())
>>> **if** x >= 10:
>>> print("**Horse**")
>>> **elif** 1 < x < 10:
>>> print("**Duck**")
>>> **else**:
>>> print("**Baguette**")
当你运行这个函数时,你会得到一个来自input()
函数的输入,假设我们输入 5,我们会得到Duck
。但是我们也可以用这样的一行程序来写整个事情:
print("**Horse**" **if** x >= 10 **else** "**Duck**" if 1 < x < 10 **else** "**Baguette**")
真的就那么简单!仔细阅读您的旧代码,您会发现许多地方可以将简单的条件 if / else 语句简化为一行程序。
说到一行程序,想只使用一行代码就获得整个数据集的概览吗?看看这个:
在不到 30 秒的时间内完成所有标准数据分析。熊猫侧写的奇迹。
towardsdatascience.com](/exploring-your-data-with-just-1-line-of-python-4b35ce21a82d)
# 5: zip()
还记得“map()
”一节中关于在两个列表之间并行应用一些东西的例子吗?zip()
让这变得更加简单。
假设我们有两个列表,一个包含名字,一个包含姓氏,我们如何有序地合并它们?使用zip()
!:
>>> first_names = ["Peter", "Christian", "Klaus"]
>>> last_names = ["Jensen", "Smith", "Nistrup"]
>>> print([' '.join(x) for x in zip(first_names, last_names)])
**['Peter Jensen', 'Christian Smith', 'Klaus Nistrup']**
哇哦!哪里弄错了,我的名字不是彼得·詹森…但是我们知道如何轻松解决这个问题!:
>>> print([' '.join(x) for x in zip(first_names, last_names[::-1])])
**['Peter Nistrup', 'Christian Smith', 'Klaus Jensen']**
更像这样
如果您喜欢这些易于应用的东西来改进您的 Python 工作流,请看看我的新文章:
让您的数据分析更上一层楼!
towardsdatascience.com](/7-things-to-quickly-improve-your-data-analysis-in-python-3d434243da7)
结束语
这只是一个简单的列表,我把它放在一起是为了让你对 Python 能做的一些伟大的事情有个印象。请留下你的任何反馈,如果你想让我解释一些具体的事情,或者如果你觉得我犯了一个错误!
感谢阅读。希望您发现这很有用!
阅读彼得·尼斯特拉普在媒介上的作品。数据科学、统计和人工智能…推特:@PeterNistrup,LinkedIn…
medium.com](https://medium.com/@peter.nistrup)
Python 技巧,从内置数据类型继承
了解如何简单地定制您的列表、字典等功能。
Image Courtesy of Greg Rakozy via Unsplash
定制列表和字典的功能,以满足您的需求!
Python 让我们设计的类继承了内置的类。内置的继承(子)类共享内置的所有相同属性(包括方法)。
我们可以有效地利用核心内置功能,但定制选定的操作。这非常有帮助,因为内置行为是所有 Python 开发人员都熟悉的。这带来了使我们的继承类易于学习的好处。
这给了我们很大的权力,因为我们的对象可以像一个字典或列表对象在各个方面的行为,除了在我们决定要它表现不同的地方。
自定义列表对象
为了说明如何利用核心对象并根据我们的需求定制它们,让我们创建一个简单的场景。
让我们构建一个只接受整数和浮点数的自定义列表类。如果我们试图追加任何其他数据类型,比如说一个字符串,我们将生成一个定制的错误异常,这将有助于通知我们类的用户这个特定列表只能接受整数和浮点数。
我们首先创建一个从 build in list 类继承的 IntFloatList 自定义类。这意味着 IntFloatList 在各个方面都像一个列表,除了在 append 被调用的时候。
我们从内置的 list 类中覆盖了现有的 append 方法。从下面的图像中,可以清楚地看到蓝色的小圆圈,旁边有红色的箭头。append 有两个参数,一个是对象(在我们的例子中是 x),另一个是我们想要追加的元素。
一个简单的条件语句,测试我们试图添加的元素是 int 还是 float 类的实例。如果不是,我将引发一个自定义的 CustomIntFloatError 异常。因为 Python 中的几乎所有东西都是对象,所以当我们引发 CustomIntFloatError 异常时,我们实际上是在创建 CustomIntFloatError 类的一个实例。
然后,我编写了一个自定义的 magic str 方法,该方法采用新构造的 CustomIntFloatError 对象,并通知用户当我们试图追加一个字符串(比如说’ four ')时,会出现一个自定义错误。
下面让我们看看它的功能!
到目前为止,一切顺利。对象 x 是一个 IntFloatList 对象,当我们将 4 或 4.5 添加到我们的列表中时,它们被正确地添加,并且列表的长度增加。但是,对于不是整数和浮点数的对象呢?
当我们试图追加字符串“four”时,会引发自定义错误异常。如控制台所示,一条错误消息通知用户 IntFloatList 是如何输出的。
When the user attempts to append a string object (here the string ‘four’), a useful error message is displayed, informing the user how the custom IntFloatList object is intended to be used.
虽然给出的例子可能不是非常有用,但它确实说明了我们如何定制内置类型来满足我们的需求。
自定义可以添加到字典中的值
为了再次演示,让我们创建一个自定义 dictionary 对象,它只能接受小于 50 的整数作为其值。
这里,我们需要从父 dict 类重新实现 setitem。setitem 是我们在字典中设置键和值时调用的神奇方法。这是一个神奇的方法,这意味着它是隐式调用的。
如果用户试图添加大于 50 的值或非整数的数据类型,将会引发自定义的 MyDictError 异常。如果没有出现异常,dict。setitem 将使用我们的对象调用,该对象将被处理,在本例中为“my_dict_object”。
我们现在可以看到 setitem,正如我们重新定义的那样,是一个与其他一些功能的挂钩,在设置键和值之前,我们可以做任何我们想做的事情。我们可以创建一个只允许某些键的字典,或者我们可以创建一个只允许某些类型的值的字典,就像这个例子所示的那样。
如果您想尝试自己运行代码片段,请使用下面显示的 GitHub gist,并进行测试。
这一次,当我试图添加一个浮点数(这里是 3.2)时,会引发一个自定义的 MyDictError 异常。输出的错误消息通知用户,当值被添加到字典中时,对该值的要求是什么。
摘要
我们可以创造功能强大但相对简单的物体。因为我们是从 list 或 dict 继承的,所以我们可以利用很多方法,而我们并没有真正意识到这一点。在这两个示例中,当没有引发异常时,将调用 parent init 和 repr 方法。
在本文中,我们学习了如何继承 Python 的内置对象,以及如何使用它们的神奇方法来改变它们的行为,同时保留它们的其他功能。
Python 对象模型的优雅赋予了这种语言整体的优雅和力量,并让它为我们所用。我们可以非常容易地将这些对象的使用传达给我们的开发伙伴。我们需要说的是,它的行为像一个列表或字典,但只是有一点不同,他们不需要学习方法名或一个新的接口,这是这种语言的一个非常强大的功能。
Python 元组从零开始!!!
让我们了解一下 python 元组的基本概念。
Image credits: GangBoard
在开始之前,我想告诉你,我将以问答的形式来写这篇教程,因为它会有所帮助,尤其是在面试的时候。在整个教程中,我将只研究一个例子来保持一致性。本教程的完整代码可以在我的 GitHub 页面上找到。
1)什么是元组,为什么使用元组?
元组是一种数据结构,用于存储异构数据,即不同类型的数据。一个元组用于将相关数据分组在一起,比如狗的名字、身高、体重、品种和颜色(我喜欢狗)。一个元组包含几个用逗号分隔的值。
2)如何创建元组?
可以通过将值放在一对括号内并用逗号分隔来创建元组,例如:
让我们创建一个称为“元组”的元组,并放入一些值,包括字符串和整数数据。这可以如下所示:
**# Creating a tuple and storing the values**tuple = (“Today’s”, “Date”, “Is”, 15, “August”, 2019)
print(tuple)**(“Today’s”, ‘Date’, ‘Is’, 15, ‘August’, 2019)**print(type(tuple))**<class 'tuple'>**
如上所述,一个元组可以保存异构数据(因此证明:)
3)我们如何访问一个元组的值?
索引可以做到这一点。元组的值可以通过它们的索引来获取。要做到这一点,您只需将数字(索引值)和元组的名称一起放在一对方括号中。
**# Accessing the values of a tuple**print(tuple[2])**'Is'**print(tuple[5])**2019**
4)如何嵌套或合并两个元组?
只要将旧元组放置在由逗号分隔的新创建的元组旁边,就可以实现两个或更多元组的嵌套。
**# Nesting two tuples as one tuple**tuple1 = (“And”, “its”, “Thursday”)
print(tuple1)**(‘And’, ‘its’, ‘Thursday’)**nest = tuple, tuple1
print(nest)**((“Today’s”, ‘Date’, ‘Is’, 15, ‘August’, 2019), (‘And’, ‘its’, ‘Thursday’))**
5)元组是不可变的还是可变的?
在回答这个问题之前,你应该知道不可变的值是不可变的,可变的值是可变的。现在让我们来回答这个问题,答案是元组是不可变的,是的,一旦元组被创建,我们就永远不能改变它们的值。不信,我证明给你看。
**# Tuples are immutable in nature**print(tuple[0])**“Today’s”****# Changing the value of the 0th index to "Hi"**tuple[0] = ("Hi")
print(tuple)**--------------------------------------------------------------------****TypeError: Traceback (most recent call last)**[**<ipython-input-12-18297fa5df7e>**](/<ipython-input-12-18297fa5df7e>) **in <module>()
----> 1 tuple[0] = ("Hi")
2 tuple****TypeError: 'tuple' object does not support item assignment**
因此,以上证明了元组在本质上是不可变的。
6)元组能在其中存储相同的数据吗?
是的,元组可以在其中存储相同的数据,我们可以在一个元组中存储许多相同的值。例如:
**# Storing identical data with a tuple**tuple = (“Today’s”, “Date”, “Is”, 15, “August”, 2019)
print(tuple)**(“Today’s”, ‘Date’, ‘Is’, 15, ‘August’, 2019)**tuple = [(“Today’s”, “Date”, “Is”, 15, “August”, 2019), (“Today’s”, “Date”, “Is”, 15, “August”, 2019)]
print(tuple)**[(“Today’s”, ‘Date’, ‘Is’, 15, ‘August’, 2019), (“Today’s”, ‘Date’, ‘Is’, 15, ‘August’, 2019)]**
如何循环遍历一个元组?
这个问题很直接,使用循环结构,我们可以循环遍历一个元组。下面我将使用 for 循环并遍历元组中的值,您可以类似地使用其他循环结构并获得结果。
tuple = (“Today’s”, “Date”, “Is”, 15, “August”, 2019)
print(tuple)**(“Today’s”, ‘Date’, ‘Is’, 15, ‘August’, 2019)**for i in tuple:
print(i)**Today’s
Date
Is
15
August
2019**
8)如何使用循环访问元组的索引?
我们可以使用带有枚举函数的 for 循环来实现这一点。枚举是 Python 的内置函数。它允许我们循环一些东西,并有一个自动计数器,了解更多关于枚举的信息,阅读它的完整文档这里。例如:
**# Accessing the index of the tuple using enumerate function.**tuple = (“Today’s”, “Date”, “Is”, 15, “August”, 2019)
print(tuple)**(“Today’s”, ‘Date’, ‘Is’, 15, ‘August’, 2019)**for counter, value in enumerate(tuple):
print(counter, value)**0 Today's
1 Date
2 Is
3 15
4 August
5 2019**
我们能从元组中移除值或项吗?
我想现在你可以轻松回答这个问题了。答案是否定的,不能从元组中删除值或项,但是可以完全删除元组。这是因为元组是不可变的。例如:
**# Deleting an entire tuple using del**tuple = (“Today’s”, “Date”, “Is”, 15, “August”, 2019)
tuple**(“Today’s”, ‘Date’, ‘Is’, 15, ‘August’, 2019)**del tuple
print(tuple)**<class 'tuple'>**
如上所述,可以使用 del 删除整个元组,所以当我们打印元组时,可以看到其中没有任何元素。
10)如何统计值在元组中出现的次数?
这可以通过使用元组的 count 方法来完成,count 方法返回一个值在元组中出现的次数。例如:
**# Counting the number of times a value has appeared in the tuple**tuple = (“Today’s”, “Date”, “Is”, 15, “August”, 2019, “And”, “Day”, “Is”, “Thursday”)
print(tuple)**("Today's", 'Date', 'Is', 15, 'August', 2019, 'And', 'Day', 'Is', 'Thursday')**print(tuple.count("Is"))
**2**print(tuple.count(15))
**1**
所以在上面的例子中,值“Is”出现了 2 次,类似地,15 出现了 1 次。
11)如何获取元组中某个值的索引?
这可以通过使用元组的索引方法来完成,索引方法搜索值的第一次出现,并返回它的位置。例如:
**# Counting the number of times a value has appeared in the tuple**tuple = (“Today’s”, “Date”, “Is”, 15, “August”, 2019, “And”, “Day”, “Is”, “Thursday”)
print(tuple)**("Today's", 'Date', 'Is', 15, 'August', 2019, 'And', 'Day', 'Is', 'Thursday')**print(tuple.index("Date"))
**1**print(tuple.index("August"))
**4**print(tuple.index("Is"))
**2**
如上所述,index 方法返回值的位置,但是在“是”的最后一种情况下,index 方法返回元组中第一次出现的“是”并返回其位置。
13)如何检查值是否存在于元组中?
这可以使用 if 语句中的关键字中的来检查。例如,让我们检查 tuple 中是否存在 August。
**# Checking for the values present in the tuple**tuple = (“Today’s”, “Date”, “Is”, 15, “August”, 2019)
print(tuple)**("Today's", 'Date', 'Is', 15, 'August', 2019)****# Case 1:**if "August" in tuple:
print(True)
print(tuple.index("August"))
else:
print(False)**True
4**--------------------------------------------------------------------**#** **Case 2:**if "September" in tuple:
print(True)
print(tuple.index("September"))
else:
print(False)**False**
如上所述,“八月”出现在元组的位置 4,但是“九月”不出现在元组中。
因此,以上是以问答格式编写的 Python 中元组的非常重要的技术或功能(通常在编程面试中非常有用)。我引用了一些来自 Python 元组的例子。我以一种简单的方式编写了本教程,这样每个人都可以理解和掌握 Python 中元组的概念,而无需事先具备编程知识或经验。如果你们对代码有什么疑问,评论区就是你们的了。