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 在数组中会强制统一类型,这加快了计算速度。

04-15 14:16