Python 数据类型
在 Python 中有许多数据类型。最常见的是float(浮点型),int(整型),str(字符串),bool(布尔),list 和 dict(字典)。
- float - 用于表示实数。
- int - 用于表示整数。
- str - 表示文本。可以使用单引号
'value'
、双引号“value”
或三引号"""value"""
来定义字符串。三引号字符串可以用在多行文本上,还可以用于注释。 - bool - 用于布尔值。
- list - 用于存储值的集合。
- dict - 用于存储键值对。
可以用 type(variable_name)
函数来检查特定变量的类型。 Python 中的运算符根据变量的类型而表现不同,每个运算符都有不同的内置方法。
下面是在 Python 中创建浮点数、整数、字符串和布尔值变量的例子。
year_of_birth = 1994
height_cm = 170.50
subject = "Data Science"
is_success = True
print(type(year_of_birth), type(height_cm), type(subject), type(is_success))
# 输出: <class 'int'> <class 'float'> <class 'str'> <class 'bool'>
Python 列表
Python 列表是一种基本的序列类型。我们可以使用此类型来存储值的集合。一个列表可以包含任何类型的值,同时一个列表也可以包含另一个列表进行嵌套。你也可以创建一个混合使用 Python 类型的列表,不过这并不常用。可以使用如下方法创建一个列表:
fruits = ["pineapple", "apple", "lemon", "strawberry", "orange", "kiwi"]
列表子集
可以用索引从列表中获取单个或多个元素。在Python中,索引从 0
开始。因此,列表中的第一个元素对应索引 0
。我们还可以使用负索引来访问元素,列表中的最后一个元素的索引为 -1
,倒数第二个元素的索引是 -2
,依此类推。我们在Python中也有一个名为 切片 的东西,可用于从列表中获取多个元素。可以这样使用: sliceable[start_index:end_index:step]
。
start_index
是切片的起始索引,此索引所在的元素包含在结果中,默认值为0
。end_index
是切片的结束索引,此索引处的元素不会被包含到结果当中,默认值将是列表的长度
。此外,如果step
为负值,则默认值可以是负的列表的长度 - 1
。如果跳过此步骤,你会得到从开始索引到结尾的所有元素。step
是索引增加的数量,默认值为1
。如果把step
设为负值,会从后向前移动。
fruits = ["pineapple", "apple", "lemon", "strawberry", "orange", "kiwi"]
fruits[1] # apple
fruits[0] # "pineapple"
fruits[-1] # "kiwi"
fruits[5] # "kiwi"
fruits[-3] # "strawberry"
# List slicing
fruits[::] # ["pineapple", "apple", "lemon", "strawberry", "orange", "kiwi"]
fruits[0:2] # ["pineapple", "apple"]
fruits[-2:-1] # ["orange"]
fruits[3:] # ["strawberry", "orange", "kiwi"]
fruits[:4] # ["pineapple", "apple", "lemon", "strawberry"]
fruits[:] # ["pineapple", "apple", "lemon", "strawberry", "orange", "kiwi"]
fruits[::-1] # ["kiwi", "orange", "strawberry", "lemon", "apple", "pineapple"]
fruits[::-2] # ["kiwi", "strawberry", "apple"]
fruits[::2] # ["pineapple", "lemon", "orange"]
# Understanding some default values
fruits[0:6:1] # 与fruits[::]的结果相同
fruits[-1:-7:-1] # 与fruits[::-1]的结果相同
操作列表
可以用
append
方法或+
(加法运算符)将单个或多个元素添加到列表当中。如果你对两个列表使用加法运算符,Python 将给出两个列表合并后的新列表。- 可以用方括号来修改列表中的单个或多个元素。
- 可以用
remove(value)
方法从列表中删除一个元素。此方法用参数传入的值删除列表中存储的第一个相同元素。
# 添加一个元素
fruits.append("peach")
fruits
#输出 ["pineapple", "apple", "lemon", "strawberry", "orange", "kiwi", "peach"]
fruits = fruits + ["fig", "melon"]
fruits
#输出 ["pineapple", "apple", "lemon", "strawberry", "orange", "kiwi", "peach", "fig", "melon"]
# 修改
fruits[0:2] = ["grape", "mango"]
fruits
#输出 ["grape", "mango", "lemon", "strawberry", "orange", "kiwi", "peach", "fig", "melon"]
# 从列表中删除
fruits.remove("mango")
fruits
#输出 ["grape", "lemon", "strawberry", "orange", "kiwi", "peach", "fig", "melon"]
了解列表背后的工作机制非常重要。当创建新列表 my_list
时,列表会存储在计算机内存中,该列表的地址被存储在 my_list
变量中。变量 my_list
不包含列表中的元素,它只包含对列表的引用。如果我们用等号去复制一个列表时,比如 my_list_copy = my_list
,你复制的只是列表的引用而不是列表的值。所以如果要复制列表实际的值,可以用 list(my_list)
函数或切片 [ : ]
。
numbers = [10, 42, 28, 420]
numbers_copy = numbers
numbers_copy[2] = 100
numbers # [10, 42, 100, 420]
numbers_copy # [10, 42, 100, 420]
ratings = [4.5, 5.0, 3.5, 4.75, 4.00]
ratings_copy = ratings[:]
ratings_copy[0] = 2.0
ratings # [4.5, 5.0, 3.5, 4.75, 4.0]
ratings_copy # [2.0, 5.0, 3.5, 4.75, 4.0]
characters = ["A", "B", "C"]
characters_copy = list(characters)
characters_copy[-1] = "D"
characters # ["A", "B", "C"]
characters_copy # ["A", "B", "D"]
Python字典
字典用于存储键值对形式的数据。当你希望通过唯一键对值进行索引时很有用。在 Python 中,可以使用花括号创建字典,键和值由冒号分隔。如果想获得给定键的值,可以这样做:our_dict[key]
。
字典与列表
让我们看一个例子,比较一下列表和词典。假如有一些电影,我们想存储它们的评级,另外还希望通过电影名称来非常快速地访问电影的评级。这时可以用两个列表或一个字典来完成这类操作。在例子中,movies.index(“Ex Machina”)
代码返回电影 “Ex Machina” 的索引。
使用列表
movies = ["Ex Machina", "Mad Max: Fury Road", "1408"]
ratings = [7.7, 8.1, 6.8]
movie_choice_index = movies.index("Ex Machina")
print(ratings[movie_choice_index]) # 7.7
使用字典
ratings = {
"Ex Machina": 7.7,
"Mad Max: Fury Road": 8.1,
"1408" : 6.8
}
print(ratings["Ex Machina"]) # 7.7
可以看出,使用字典更加直观和方便。
操作字典
可以对词典中的数据进行添加,更新和删除操作。当添加或更新数据时,可以简单地使用 our_dict[key] = value
,想要删除一个键值对时,可以用 del(our_dict[key])
操作。
ratings["Deadpool"] = 8.0
print(ratings)
# {'Ex Machina': 7.7, 'Mad Max: Fury Road': 8.1, '1408': 6.8, 'Deadpool': 8.0}
ratings["Ex Machina"] = 7.8
print(ratings)
# {'Ex Machina': 7.8, 'Mad Max: Fury Road': 8.1, '1408': 6.8, 'Deadpool': 8.0}
del(ratings["1408"])
print(ratings)
# {'Ex Machina': 7.8, 'Mad Max: Fury Road': 8.1, 'Deadpool': 8.0}
还可以检查给定的键是否在字典中:key in our_dict
。
print("Ex Machina" in ratings) # True
函数
函数是解决特定问题的可重用代码。可以用 def
关键字编写函数:
def is_prime(n):
if n <= 1:
return False
elif n <= 3:
return True
elif n % 2 == 0 or n % 3 == 0:
return False
current_number = 5
while current_number * current_number <= n:
if n % current_number == 0 or n % (current_number + 2) == 0:
return False
current_number = current_number + 6
return True
不过 Python 中有许多内置函数,例如 max( iterable[,key] )
,min( iterable [,key] )
,type( object )
,round( number[,ndigits] )
等。所以当我们需要一个解决某个问题的函数时,可以先研究一下是否存在相关的内置函数或 Python 包。没有必要去“重新发明轮子”。
方法
我们已经知道 Python 中有字符串,浮点数,整数,布尔值等类型。这些数据结构都是一个对象。方法是一种可用于给定对象的函数,具体取决于对象的类型。所以每个对象都有一个特定的类型和一组方法,具体形式取决于给出的类型。
# 字符串方法
text = "Data Science"
text.upper() # "DATA SCIENCE"
text.lower() # "data science"
text.capitalize() # "Data science"
# 列表方法
numbers = [1, 4, 0, 2, 9, 9, 10]
numbers.reverse()
print(numbers) # [10, 9, 9, 2, 0, 4, 1]
numbers.sort()
print(numbers) # [0, 1, 2, 4, 9, 9, 10]
# 字典方法
ratings = {
"Ex Machina": 7.7,
"Mad Max: Fury Road": 8.1,
"1408" : 6.8
}
print(ratings.keys()) # dict_keys(['Ex Machina', 'Mad Max: Fury Road', '1408'])
print(ratings.values()) # dict_values([7.7, 8.1, 6.8])
print(ratings.items()) # dict_items([('Ex Machina', 7.7), ('Mad Max: Fury Road', 8.1), ('1408', 6.8)])
不同类型的对象可以有相同名称的方法。根据对象的类型,方法有各自不同的行为。
numbers = [10, 30, 55, 40, 8, 30]
text = "Data Science"
numbers.index(8) # 4
text.index("a") # 1
numbers.count(30) # 2
text.count("i") # 1
务必要小心!某些方法可以更改调用它们的对象。例如在列表类型上调用append()
方法时。
包
模块是包含 Python 定义和声明的文件。用于定义解决特定问题的函数、方法和新的 Python 类型。
包是模块的集合。有许多 Python 包涵盖了不同领域的解决方案。例如,NumPy、matplotlib、seaborn 和 scikit-learn 是非常着名的数据科学支持包。
- NumPy 用于有效地处理数组
- matplotlib 和 seaborn 是流行的数据可视化库
- scikit-learn 是一个功能强大的机器学习库
默认情况下,Python 中有一些内置包,但是我们还需要更多的包,这些默认是不安装的。如果想要使用某个软件包,它就必须是已经安装好的,或者先用 pip 安装( Python的包管理系统 )。
另外,还有一种叫做Anaconda 的东西。
所以如果你不想安装太多的包,我建议你用 Anaconda。这个发行版中有很多有用的包。
导入声明
安装所需的包后,可以把它们导入 Python 代码文件。可以从中导入整个包、子模块或特定函数。另外还可以为包设置别名。可以从下面的例子中看到 import 语句的不同方式。
简单的导入
import numpy
numbers = numpy.array([3, 4, 20, 15, 7, 19, 0])
导入的同时设置别名
import numpy as np # np 是 numpy 包的别名
numbers = np.array([3, 4, 20, 15, 7, 19, 0]) # 工作正常
numbers = numpy.array([3, 4, 20, 15, 7, 19, 0]) # 出错,NameError: name 'numpy' is not defined
从包导入子模块并设置别名
# 从 matplotlib 包中导入 pyplot 子模块并设置别名 "plt"
import matplotlib.pyplot as plt
仅从包中导入一个函数
from numpy import array
numbers = array([3, 4, 20, 15, 7, 19, 0]) # 工作正常
numbers = numpy.array([3, 4, 20, 15, 7, 19, 0]) # 出错,NameError: name 'numpy' is not defined
type(numbers) # 输出:numpy.ndarray
我们也可以这样导入: from numpy import *
。星号表示从该模块导入所有内容。这条 import 语句会在当前命名空间中为 numpy
模块定义的所有公共对象创建引用。换句话说,我们可以使用 numpy
中的所有可用函数,在函数名称可以不带前缀。例如,现在我们可以这样使用 NumPy 的绝对值函数: absolute()
,而不是numpy.absolute()
。
但是,我不建议你使用它,因为:
- 如果从某些模块中导入所有函数,那么当前的命名空间将填充过多的函数,如果有人查看我们的代码的话,他可能会对某个函数到底属于哪个包而感到困惑。
- 如果两个模块具有相同名称的函数,则第二个导入的将会覆盖第一个模块的函数。
NumPy
NumPy 是用 Python 进行科学计算的基础包。它非常快速且易于使用。这个包能够帮助我们按元素进行计算(逐个元素)。
常规的 Python 列表不知道如何以元素方式进行操作。当然我们也可以用 Python 列表去做科学计算,但是它非常慢,而且还需要编写更多的代码来得到想要的结果。更多时候使用 NumPy 才是一个聪明的主意。
与常规 Python 列表不同,NumPy 数组中的元素总是只有一种类型。如果我们将一个不同类型的数组传递给np.array()
,可以用参数 dtype
设定想要的类型。如果没有给出此参数,则会将类型确定为保存对象所需的最小类型。
NumPy 数组 —— 类型转换
np.array([False, 42, "Data Science"]) # array(["False", "42", "Data Science"], dtype="<U12")
np.array([False, 42], dtype = int) # array([ 0, 42])
np.array([False, 42, 53.99], dtype = float) # array([ 0. , 42. , 53.99])
# 无效的类型转换
np.array([False, 42, "Data Science"], dtype = float) # 不会把字符串 'Data Science' 转化为浮点型
NumPy 数组有自己的属性和方法。你是不是还记得前面说过 Python 运算符在不同的数据类型上表现也不一样?在NumPy 中运算符在这方面表现得很好。
NumPy 数组上的运算符
np.array([37, 48, 50]) + 1 # array([38, 49, 51])
np.array([20, 30, 40]) * 2 # array([40, 60, 80])
np.array([42, 10, 60]) / 2 # array([ 21., 5., 30.])
np.array([1, 2, 3]) * np.array([10, 20, 30]) # array([10, 40, 90])
np.array([1, 2, 3]) - np.array([10, 20, 30]) # array([ -9, -18, -27])
如果检查 NumPy 数组的类型,结果会是 numpy.ndarray
。 ndarray 意味着是 n 维数组。在前面的例子中用了一维数组,但是也可以使用 2, 3, 4 甚至更多维数组。我们可以在数组上进行子集化,而这与该数组的维数无关。下面是一些二维数组的例子。
二维数组的子集
numbers = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]
])
numbers[2, 1] # 8
numbers[-1, 0] # 10
numbers[0] # array([1, 2, 3])
numbers[:, 0] # array([ 1, 4, 7, 10])
numbers[0:3, 2] # array([3, 6, 9])
numbers[1:3, 1:3] # array([[5, 6],[8, 9]])
如果想要知道一个 numpy 数组有多少个维度,以及每个维度有多少个元素,可以用 shape
属性。下面的代码得到二维数组的shape,返回的元组中的第一个元素是行数,第二个元素是列数。
NumPy 的 shape
属性
numbers = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12],
[13, 14, 15]
])
numbers.shape # (5, 3)
基本统计
分析数据的第一步是熟悉数据。 NumPy 有一些基本方法来帮助我们做到这一点。
np.mean()
- 返回算术平均值(元素之和除以元素的个数)。np.median()
- 返回中位数(传入的数组的中间值,如果数组的长度是偶数,将计算两个中间值的平均值)np.corrcoef()
- 返回一个相关矩阵。当我们想要查看数据集中两个变量之间是否存在相关性时,或者在两个具有相同长度的数组之间存在相关性时,这个函数非常有用。np.std()
- 返回标准偏差
learning_hours = [1, 2, 6, 4, 10]
grades = [3, 4, 6, 5, 6]
np.mean(learning_hours) # 4.6
np.median(learning_hours) # 4.0
np.std(learning_hours) # 3.2
np.corrcoef(learning_hours, grades)
# 输出:[[ 1. 0.88964891][ 0.88964891 1. ]]
使用 NumPy 生成基本统计信息
从上面的例子中,我们可以看到学习时间和成绩之间存在高度相关性。
此外还可以看到:
- 学习时间的平均值是 4.6
- 学习时间的中位数为 4.0
- 学习时间的标准差为 3.2
NumPy 还有一些基本函数,如 np.sort()
和 np.sum()
,在基本的 Python 列表中也有同样的函数。不过需要注意的是 NumPy 在数组中会强制统一类型,这加快了计算速度。