Python 基础 (Pandas):Pandas 入门

1. 官方文档

API reference — pandas 2.2.2 documentation

2. 准备知识:Pandas 数据结构 Series & DataFrame

2.1 Series

2.1.1 创建 Series 类型数据

一个 Series 对象包含两部分:值序列、标识符序列。可通过 .values (返回 NumPy ndarry 类型数据) 和 .index (返回 Pandas Index 类型数据) 分别获取这两部分内容。

Pandas 中的 Index 对象是一个不可变的数组,用于标识 DataFrame 或 Series 中的行或列。Index 可以是整数、字符串或其他对象类型。

RangeIndex 是一种特殊类型的 Index,它是一个基于整数的 Index,用于表示连续的整数范围。 RangeIndex 是 Pandas 默认的Index类型,如果没有指定 Index 类型,则会自动使用RangeIndex。与普通的Index相比,RangeIndex 具有更高的性能,因为它不需要存储所有的值,而是只需要存储起始值、结束值和步长即可,此外,RangeIndex 还支持一些特殊的操作,如切片、重置索引等。

Series 可以有任意类型的显示索引 (可将其看作是行的标签 explicit index, label index) 。类似于 numpy.array,Series 也有隐式整数索引 (implicit index,位置索引 positional index),可指示元素在系列中的位置。如果创建 Series 时没有指定索引信息,显示索引采用隐式索引值。

类似于 dict,Series 也支持 .key() 和 in 关键字。

# s1 behaves like a Python dictionary because it features both a positional and a label index.
s1 = pd.Series([4200, 8000, 6500],index=["Amsterdam", "Toronto", "Tokyo"])

# s2 behaves like a Python list because it only has a positional index
s2 = pd.Series([5555, 7000, 1980])

# construct a Series with a label index from a Python dictionary
s3 = pd.Series({"Amsterdam": 5, "Tokyo": 8})

s1
s2
s3
# 返回结果:
# Amsterdam    4200
# Toronto      8000
# Tokyo        6500
# dtype: int64

# 0    5555
# 1    7000
# 2    1980
# dtype: int64

# Amsterdam    5
# Tokyo        8
# dtype: int64
s1.values
# array([4200, 8000, 6500], dtype=int64)
s1.index
# Index(['Amsterdam', 'Toronto', 'Tokyo'], dtype='object')

type(s1.values)  
# numpy.ndarray
type(s1.index)   
# pandas.core.indexes.base.Index
type(s2.index)
# pandas.core.indexes.range.RangeIndex

s1.keys()  
# Index(['Amsterdam', 'Toronto', 'Tokyo'], dtype='object')
s2.keys()
# RangeIndex(start=0, stop=3, step=1)

"Amsterdam" in s2
# False
"Amsterdam" in s3
# True

2.1.2 获取 Series 中元素

way1: 索引操作符 (建议仅用于临时分析)

索引操作符方括号+索引 如:[label]

import pandas as pd

city_revenues = pd.Series({"Amsterdam": 4200, "Toronto": 8000, "Tokyo":6500})
city_revenues["Toronto"]
# 8000

city_revenues["Toronto":]
# Toronto    8000
# Tokyo      6500
# dtype: int64

# city_revenues[1]  # 将弃用
# Series.__getitem__ treating keys as positions is deprecated. In a future version, 
# integer keys will always be treated as labels (consistent with DataFrame behavior). 
# To access a value by position, use `ser.iloc[pos]`
s1 = pd.Series([1, 4, 5, 8])

s1[3]
# 8

s1[2:4]
# 2    5
# 3    8
# dtype: int64
way2: .loc[] & .iloc[] (推荐使用 pandas-specific access methods)

(1).loc[] 方法 (采用标签索引)

(2).iloc[] 方法 (采用位置索引)

.loc 和 .iloc 支持索引操作符的特性,如切片。不过,.loc 和 .iloc 有一个重要的区别:.iloc 不含最大值,但.loc 包含。

s1 = pd.Series({1: 'A', 2: 'B', 3:'C', 5:'D', 8:'E', 10:'F'})

# .loc[] 标签索引; .iloc[] 位置索引
s1.loc[1]
# 'A'
s1.iloc[1]
# 'B'

s1.loc[[1, 3, 5]]
# 1    A
# 3    C
# 5    D
# dtype: object

s1.iloc[[1, 3, 5]]
# 2     B
# 5     D
# 10    F
# dtype: object

# .iloc 不包括最大值,.loc 包含。
s1.loc[1:3]
# 1    A
# 2    B
# 3    C
# dtype: object

s1.iloc[1:3]
# 2    B
# 3    C
# dtype: object

s1.iloc[-1]
# 'F'

2.2 DataFrame

2.2.1 创建 DataFrame 类型数据

DataFrame 是一系列具有相同索引的 Series 对象。可通过在构造函数中传递字典 (字典键为列名,值为 Series 对象),将这些 Series 对象组合成一个DataFrame。

可以把 DataFrame 的两个维度称为坐标轴,.axes 返回轴信息,需要注意的是,0 对应行索引,1 对应列索引,了解这个术语很重要,因为很多 DataFrame 方法接受 axis 参数。

DataFrame 也是一种类似字典的数据结构,因此它也支持 .keys() 和 in 关键字。不过,对于一个DataFrame,这些与索引无关,而是与列名有关。

import math
import pandas as pd
import numpy as np

city_revenues = pd.Series({"Amsterdam": 4200, "Toronto": 8000, "Tokyo":6500})
city_employee_count = pd.Series({"Amsterdam": 5, "Tokyo": 8})
city_data = pd.DataFrame({
 "revenue": city_revenues,
 "employee_count": city_employee_count
})


city_data.index
# Index(['Amsterdam', 'Tokyo', 'Toronto'], dtype='object')
city_data.values
# array([[4.2e+03, 5.0e+00],
#        [6.5e+03, 8.0e+00],
#        [8.0e+03,     nan]])
city_data.axes
# [Index(['Amsterdam', 'Tokyo', 'Toronto'], dtype='object'),
#  Index(['revenue', 'employee_count'], dtype='object')]

type(city_data.index)
# pandas.core.indexes.base.Index
type(city_data.values)
# numpy.ndarray
type(city_data.axes)
# list
type(city_data.axes[0])
# pandas.core.indexes.base.Index

注意 "Toronto" 缺少 employee_count 值,自动替换为 NaN。

math.isnan(city_data.iloc[2,1])
# True
np.isnan(city_data.iloc[2,1])
# True
pd.isna(city_data.iloc[2,1])
# True

2.2.2 获取 DataFrame 中元素

way1: 索引操作符 (建议仅用于临时分析)

可使用索引运算符选择指定名称的列,如果列名是字符串,那么你也可以使用属性风格的点表示法访问 (当列名也是 DataFrame 属性或方法名时,不能采用点表示法)

import pandas as pd

city_revenues = pd.Series({"Amsterdam": 4200, "Toronto": 8000, "Tokyo":6500})
city_employee_count = pd.Series({"Amsterdam": 5, "Tokyo": 8})
city_data = pd.DataFrame({
 "revenue": city_revenues,
 "employee_count": city_employee_count
})

city_data['revenue']
# Amsterdam    4200
# Tokyo        6500
# Toronto      8000
# Name: revenue, dtype: int64

city_data.revenue
# Amsterdam    4200
# Tokyo        6500
# Toronto      8000
# Name: revenue, dtype: int64
way2: .loc[] & .iloc[] (推荐)

1个参数 -- 行

city_data.loc['Tokyo']
# revenue           6500.0
# employee_count       8.0
# Name: Tokyo, dtype: float64

city_data.iloc[0]
# revenue           4200.0
# employee_count       5.0
# Name: Amsterdam, dtype: float64

city_data.loc['Tokyo':"Toronto"]
# 	revenue	employee_count
# Tokyo	6500	8.0
# Toronto	8000	NaN

2个参数 -- 行,列

city_data.loc[:, "revenue"]
# Amsterdam    4200
# Tokyo        6500
# Toronto      8000
# Name: revenue, dtype: int64

city_data.iloc[1:, :]
# 	revenue	employee_count
# Tokyo	6500	8.0
# Toronto	8000	NaN

当取单行或者单列时,需要注意返回值是 Series (int\str) 还是 DataFrame (list)。

city_data['revenue']    # Series
city_data[['revenue']]  # DataFrame
city_data.iloc[1]       # Series
city_data.iloc[[1]]     # DataFrame
city_data.iloc[[]]      # DataFrame

3. 实践:数据的读取及初步查看

3.1 代码

import requests
import pandas as pd
import numpy as np

# 1.获取数据

download_url = "https://raw.githubusercontent.com/fivethirtyeight/data/master/nba-elo/nbaallelo.csv"
target_csv_path = "nba_all_elo.csv"

response = requests.get(download_url, verify=False)
response.raise_for_status()    # Check that the request was successful
with open(target_csv_path, "wb") as f:
    f.write(response.content)
print("Download ready.")

# 2. 读取数据
nba = pd.read_csv('nba_all_elo.csv')

# 3. 初步查看数据信息
len(nba)
nba.shape

pd.set_option("display.max.columns", None)
pd.set_option("display.precision", 2)
nba.head()

nba.info()
nba.dtypes

nba.describe()

nba.describe(include=object)


# 按条件筛选数据
current_decade = nba[nba["year_id"] > 2010]
current_decade.shape
# (12658, 23)

games_with_notes = nba[nba["notes"].notnull()]
games_with_notes.shape
# (5424, 23)

games_with_notes = nba[nba["notes"].notna()]
games_with_notes.shape
# (5424, 23)

ers = nba[nba["fran_id"].str.endswith("ers")]
ers.shape
# (27797, 23)

nba[(nba["_iscopy"] == 0) & (nba["pts"] > 100) & (nba["opp_pts"] > 100) & (nba["team_id"] == "BLB")]

3.2 细节说明

3.2.1 获取数据:request 库

verify 参数

SSL证书:是数字证书的一种,类似于驾驶证、护照和营业执照的电子副本。因为配置在服务器上,也称为SSL服务器证书。SSL 证书就是遵守 SSL协议,由受信任的数字证书颁发机构CA(也可称为CA证书),在验证服务器身份后颁发,具有服务器身份验证和数据传输加密功能。

在使用 requests.get 时,如果请求的目标网站使用了自签名的SSL证书或者是无效的证书(SSLError异常),就需要设置 verify=False,这样可以忽略证书验证错误,使得请求可以正常发送。但是需要注意的是,这样做会存在一定的安全风险,因为无法保证请求的目标网站的身份和数据的安全性。因此,建议只在必要的情况下使用 verify=False。

verify参数适用场景

  • https 类型网站,但是没有经过证书认证机构认证,考虑使用 verify 参数
  • 程序中抛出 SSLError 异常,考虑使用 verify 参数

3.2.2 读入数据

read_csv 函数关键参数说明

- filepath_or_buffer:要读取的文件路径或者URL。

- sep:分隔符,默认为逗号。

- header:包含列名并标记数据开始(零索引)的行号。默认为 header=0,即第一行。header 可以是一个整数列表,用于指定 MultiIndex 的行位置,例如 [0,1,3]。未指定的中间行将被跳过。

- index_col:指定某一列作为行索引。

- usecols:指定要读取哪些列。

- dtype:指定应用于整个数据集或单个列的数据类型。例如,{'a': np。float64, 'b': np.int32, 'c': 'Int64'} 。

- skiprows:跳过前几行。

- nrows:读取的行数。

- na_values:指定哪些值为缺失值。

read_excel 函数关键参数说明

- io:要读取的Excel文件路径,可以是本地文件路径或URL。

- sheet_name:指定要读取的工作表名称或索引。

- header:指定哪一行作为列名,默认为0,即第一行。

- index_col:指定某一列作为行索引。

- usecols:指定要读取哪些列。

- dtype:指定列的数据类型。

- skiprows:跳过前几行。

- nrows:读取的行数。

- na_values:指定哪些值为缺失值。

3.2.3 初步查看数据信息

显示所有列

pd.set_option("display.max.columns", None)
pd.set_option("display.precision", 2)
nba.head()

所有列都能显示 (没有...)

查看每列的数据类型

.info()

.info() 除了可以各列的数据类型,还能显示数据缺失,以及内存占用情况。

.dtypes

查看各列的描述性统计量

.describe()

.describe(include=object)

按条件查询数据

.notna() 和 .notnull() 方法在 pandas 中是等价的,它们都可以用于检查 DataFrame 或 Series 中的缺失值。这两种方法都返回一个布尔型的 DataFrame 或 Series,其中缺失值对应的位置为 False,非缺失值对应的位置为 True。

如需组合多个条件,将条件放在括号中,并使用操作符 | 和 & 来分隔。

  1. Python 的逻辑运算符有: and、not 和 or,优先级低于算术运算符,如<、<=、>、>=、!= 和 ==。
  2. pandas (以及NumPy) 不使用 and、or 或 not,而是使用 &、| 和 ~ (Python 内置位操作符,在pandas 和 NumPy 中,可以把 “按位” 想象成 “按元素”),它们的优先级高于 (而不是低于) 算术运算符,当在一个表达式中同时使用 & 运算符和算数运算符时,& 运算符会先被执行,如果想要改变运算顺序,需要使用圆括号来明确运算顺序。
4 < 3 and 5 > 4
# False

3 and 5
# 5
# 3 and 5 返回 5,是因为逻辑运算符 short-circuit evaluation,返回最后求值的实参
# 短路运算符(&&和||)在求值时,如果已经可以确定整个表达式的值,则不会继续求值剩余的部分,而是直接返回最后求值的实参的值。
# 具体来说,对于&&运算符,如果第一个实参为false,则整个表达式的值为false,不会继续求第二个实参;
# 如果第一个实参为true,则整个表达式的值取决于第二个实参的值,会继续求值第二个实参并返回其值。
# 对于||运算符,如果第一个实参为true,则整个表达式的值为true,不会继续求值第二个实参;
# 如果第一个实参为false,则整个表达式的值取决于第二个实参的值,会继续求值第二个实参并返回其值。

4 < (3 and 5) > 4
# True
pd.Series([True, True, False]) & pd.Series([True, False, False])
# 0     True
# 1    False
# 2    False
# dtype: bool

s = pd.Series(range(10))
# 带括号 -- 正确
(s % 2 == 0) & (s > 3)
# 0    False
# 1    False
# 2    False
# 3    False
# 4     True
# 5    False
# 6     True
# 7    False
# 8     True
# 9    False
# dtype: bool

# 不带括号 -- 报错
# s % 2 == 0 & s > 3  # 报错
# ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
# 等价于 (s % 2) == (0 & s) and ((0 & s) > 3)
# 说明: Expansion the statement:x < y <= z is equivalent to x < y and y <= z.


left = (s % 2) == (0 & s)
# 0     True
# 1    False
# 2     True
# 3    False
# 4     True
# 5    False
# 6     True
# 7    False
# 8     True
# 9    False
# dtype: bool

right = (0 & s) > 3
# 0    False
# 1    False
# 2    False
# 3    False
# 4    False
# 5    False
# 6    False
# 7    False
# 8    False
# 9    False
# dtype: bool

# left and right  # 报错
# The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
# The problem is that pandas developers intentionally don’t establish a truth-value (truthiness) for an entire Series. 
# Is a Series True or False? Who knows? The result is ambiguous.

left & right
# 0    False
# 1    False
# 2    False
# 3    False
# 4    False
# 5    False
# 6    False
# 7    False
# 8    False
# 9    False
# dtype: bool

4. DataFrame 常用操作

4.1 分组 Grouby & 聚合运算 agg

pandas 库提供了分组 Groupby 和聚合函数 agg 用以表达数据集的其他特征,例如分组统计元素的总和、平均值或平均值。

agg方法常与groupby一起使用,用于对分组后的数据进行聚合计算。agg 方法可以接受一个或多个聚合函数,将这些函数应用于每个分组,并返回一个DataFrame对象。

常用的聚合函数包括:

  1. sum():计算每个分组的总和。
  2. mean():计算每个分组的平均值。
  3. median():计算每个分组的中位数。
  4. min():计算每个分组的最小值。
  5. max():计算每个分组的最大值。
  6. count():计算每个分组的数量。
  7. std():计算每个分组的标准差。
  8. var():计算每个分组的方差。

示例1 下述代码用于描述:Golden State Warriors 队在2014-15赛季(year_id: 2015),在常规赛和季后赛中,胜负各有多少场。pandas 在调用 .groupby() 时会对组键进行排序。如果不需要排序,可以传递 sort=False,此参数可以提高性能。 

nba[(nba["fran_id"] == "Warriors") & (nba["year_id"] == 2015)].groupby(["is_playoffs", "game_result"], sort=False)["game_id"].count()

返回结果 (Series):

is_playoffs  game_result
0            W              67
             L              15
1            W              16
             L               5
Name: game_id, dtype: int64

示例2 采用多个聚合函数时

nba_grp = nba.loc[(nba.loc[:,"year_id"] > 2013) & (nba.loc[:,"pts"] > 130)].groupby(['year_id',"team_id"])["pts"].agg(['count', 'mean'])

返回结果 (DataFrame 过长,此处仅展示部分内容):

针对多重索引 DataFrame 的一些操作:

nba_grp.index.names = ['year', 'team']  # 修改多重索引名称
nba_grp.sort_index(level=0, axis=0)     # 按行索引0 - year 排序
nba_grp.sort_index(level=1, axis=0)     # 按行索引1 - team 排序
nba_grp.swaplevel(axis=0)               # 交换多重索引级别
nba_grp.reset_index()                   # 展开为一维索引

结果展示 (数据过长,此处仅展示部分内容):

原始表 改名+排序 (level0)  排序 (level1) 调换多重索引顺序 展平 
 countmean countmean countmean countmean yearteamcountmean
year_idteam_idyearteamyearteamteamyear02014DEN3136
2014DEN31362014DEN31362015ATL1131DEN2014313612014HOU2139.5
HOU2139.5HOU2139.5BOS1132HOU20142139.522014LAC3139
LAC3139LAC3139DAL5136.4LAC2014313932014MIN2137.5
MIN2137.5MIN2137.52014DEN3136MIN20142137.542014NOP3132.67
NOP3132.67NOP3132.672015DEN1143NOP20143132.6752014OKC1131
OKC1131OKC1131GSW3133.33OKC2014113162014POR2136.5
POR2136.5POR2136.52014HOU2139.5POR20142136.572014SAS1133
SAS1133SAS1133LAC3139SAS2014113382014UTA1136
UTA1136UTA1136MIN2137.5UTA2014113692014WAS1134
WAS1134WAS1134NOP3132.67WAS20141134102015ATL1131
2015ATL11312015ATL11312015NOP1139ATL20151131112015BOS1132

4.2 增删行列、重命名等

下述代码包含修改列名、新增行\列、删除列\行、删除重复行\列、删除全为0的行\列、修改行名\列名。代码没有明确的实际含义,仅用于体现上述操作如何实现。

df = nba.iloc[:100, :].copy(deep=True)

# 新增行
## 增加一个重复行
df = pd.concat([df, df.iloc[[0]]], axis=0, ignore_index=True)
## 增加一个全为 NAN 的行
df_nan_row = pd.DataFrame([[np.nan] * df.shape[1]], columns=df.columns)
df = pd.concat([df, df_nan_row], axis=0, ignore_index=True)

# 新增列
df["difference"] = df.pts - df.opp_pts
## 新增一个新列 (原始数据中某列经过变换得到的)
df.insert(loc=1, column='year', value=df.loc[:, 'date_game'].apply(lambda v: v[-4:] if isinstance(v, str) and len(v) > 4 else v))
## 新增一个重复列,列名不重复,内容是重复的
df.insert(loc=2, column='game_id2', value=df.loc[:, 'game_id'])
## 新增一个重复列,列都是重复的
df.insert(loc=2, column='game_id', value=df.loc[:, 'game_id'], allow_duplicates=True)

# 删除某(几)行
df.drop(index=[1,2], inplace=True)       # 当前索引序列为:0 3 4 5 ... (对应行的索引号将被删除)
df.iloc[:5, :5].head()
# 	gameorder	year	game_id	game_id2	game_id
# 0	1.0	1946	194611010TRH	194611010TRH	194611010TRH
# 3	2.0	1946	194611020CHS	194611020CHS	194611020CHS
# 4	3.0	1946	194611020DTF	194611020DTF	194611020DTF
# 5	3.0	1946	194611020DTF	194611020DTF	194611020DTF
# 6	4.0	1946	194611020PRO	194611020PRO	194611020PRO
df.reset_index(drop=True, inplace=True)  # 调整索引为顺序值:0 1 2 3 ...
df.iloc[:5, :5].head()
# gameorder	year	game_id	game_id2	game_id
# 0	1.0	1946	194611010TRH	194611010TRH	194611010TRH
# 1	2.0	1946	194611020CHS	194611020CHS	194611020CHS
# 2	3.0	1946	194611020DTF	194611020DTF	194611020DTF
# 3	3.0	1946	194611020DTF	194611020DTF	194611020DTF
# 4	4.0	1946	194611020PRO	194611020PRO	194611020PRO

# 删除某(几)列
df.drop(columns=['lg_id'], inplace=True)

# 删除重复行
df.shape  # (100, 26)
df.drop_duplicates(keep='last', inplace=True)
df.shape  # (99, 26)

# 删除重复列
# df = df.T.drop_duplicates().T  # 慎用
# 经过两次转置,原来列的数据类型可能会改变,但如果用drop会将同名的两个列都删掉
df = df.loc[:, ~df.T.duplicated(keep='first')]
df.shape  # (99, 24)

# 删除全为0的行以及全为0的列 -- 当前数据没有全为0的行或列
df.drop(index=df.index[(df == 0).all(axis=1)], inplace=True)
df.drop(columns=df.columns[(df == 0).all(axis=0)], inplace=True)
df.shape  # (99, 24)

# 去掉所有值都为 nan 的行
df.drop(index=df.index[df.loc[:, df.columns[df.dtypes != 'object']].map(lambda v: np.isnan(v)).all(axis=1)], inplace=True)
df.shape  # (98, 24)

# 列重命名
df.rename(columns={"elo_i":"elo_n", "opp_elo_i":"opp_elo_n"}, inplace=True)
# 把某列设置为 index
df.insert(loc=0, column='id', value=range(1000, 1000+df.shape[0]))
df.set_index('id', inplace=True)
df.head()

4.3. 设置数据类型

# 先整体看一下数据,判断字符串中第一位是月还是日
# 注意到有 10/31/1997,因此第一位是月
# nba['date_game'].value_counts()
nba.insert(loc=nba.columns.get_loc('date_game'), 
           column='date_game_dt', 
           value=pd.to_datetime(nba.loc[:,"date_game"], format='%m/%d/%Y'))
nba.head()
nba.drop(columns=['date_game'], inplace=True)
nba.head()

nba["game_location"] = pd.Categorical(nba.loc[:,"game_location"])
nba["game_result"] = pd.Categorical(nba.loc[:,"game_result"])
nba.dtypes

5. 实践:Cleaning Data 数据清洗

在数据分析过程中,初始拿到的数据通常从不同的源收集而来,可能存在错误、缺失值、重复值、异常值等问题,数据清洗是为了去除这些问题,使数据变得更加准确、可靠和有用。数据清洗的过程通常包括数据去重、数据填充、数据转换、数据规范化等步骤。通过数据清洗,可以提高数据的质量和可靠性,为后续的数据分析提供更好的基础。

5.1 缺失值

nba.shape

# way1:删除有缺失值的行或列
rows_without_missing_data = nba.dropna(axis=0)
rows_without_missing_data.shape
columns_without_missing_data = nba.dropna(axis=1)
columns_without_missing_data.shape
columns_without_missing_data.columns


# way2:填充
nba["notes"].fillna(value="no notes at all", inplace=True)

5.2 异常值

可以根据 describe() 结果,由数据范围初步判断是否有可能存在异常值。比如在当前的数据中,year_id 列中值的范围是:1947年~2015年,看起来很合理;但是 pts (投球得分) 列最小值是0,这显然不合理,进一步查询发现只有一行数据中,pts 为0,这场比赛可能被取消了,将这行数据从数据集中删去。

5.3 数据不一致

有时候,某个值真实存在没有缺失,但与其他列中的值不匹配,为此可以定义一些互斥的查询条件,验证是否有数据不一致的现象。

比如在当前数据集中,字段 pts、opp_pts 和 game_result 应保持一致 (结果为 “W” 时,pts 应大于 opp_pts;结果为 “L” 时,pts 应小于 opp_pts)。可以使用.empty属性来检查。

代码及结果如下,当前数据集不存在违反上述条件的条目。

nba[(nba["pts"] > nba["opp_pts"]) & (nba["game_result"] != 'W')].empty
# True

nba[(nba["pts"] < nba["opp_pts"]) & (nba["game_result"] != 'L')].empty
# True

参考链接

【Python_requests学习笔记(四)】requests模块中verify参数用法_requests verify-CSDN博客

Using pandas and Python to Explore Your Dataset – Real Python

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/572979.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C语言扫雷游戏完整实现(下)

文章目录 前言一、排雷函数菜单二、排雷函数菜单的实现三、拓展棋盘功能四、源码1. test.c源文件2. game.h头文件3. game.c源文件 总结 前言 C语言实现扫雷游戏的排雷菜单&#xff0c;以及功能的实现&#xff0c;拓展棋盘功能&#xff0c;以及源码等。 上半部分的链接地址: C语…

第十五届蓝桥杯省赛第二场PythonB组B题【逆序对期望】题解(AC)

解题思路 枚举所有的可能的交换情况&#xff0c;时间复杂度 O ( n 4 ) O(n^4) O(n4)。 用归并排序计算数组的逆序对&#xff0c;时间复杂度 O ( n ) O(n) O(n)。 综上时间复杂度 O ( n 5 ) O(n^5) O(n5)。 由于 Python 运行效率较低&#xff0c;约 500 500 500 秒可得到…

前端框架技术调研

目前程序员使用前端框架最多的是哪一个&#xff1f;

SEGGER Embedded Studio IDE移植FreeRTOS

SEGGER Embedded Studio IDE移植FreeRTOS 一、简介二、技术路线2.1 获取FreeRTOS源码2.2 将必要的文件复制到工程中2.2.1 移植C文件2.2.2 移植portable文件2.2.3 移植头文件 2.3 创建FreeRTOSConfig.h并进行配置2.3.1 处理中断优先级2.3.2 configASSERT( x )的处理2.3.3 关于系…

echarts树图-实现拓扑图效果

使用echarts树图来实现拓扑图效果&#xff0c;其效果如下&#xff1a; 代码如下&#xff1a; const data {name: XXX公司,children: [{name: 网络主机,children: [{name: 普通路由器,children: [{name: 智能网关},{name: 192.168.1.0/24}]}]},{name: 企业路由器},{name: 三…

【分享】WinRAR软件如何压缩文件?

WinRAR是一款功能强大的压缩文件管理工具&#xff0c;支持多种压缩文件格式&#xff0c;那如何使用WinRAR来压缩文件呢&#xff1f;不清楚的小伙伴一起来看看吧&#xff01; 压缩方法&#xff1a; 首先&#xff0c;安装好WinRAR工具&#xff0c;然后选中需要压缩的文件或文件夹…

C++高级特性:异常概念与处理机制(十四)

1、异常的基本概念 异常&#xff1a;是指在程序运行的过程中发生的一些异常事件&#xff08;如&#xff1a;除数为0&#xff0c;数组下标越界&#xff0c;栈溢出&#xff0c;访问非法内存等&#xff09; C的异常机制相比C语言的异常处理&#xff1a; 函数的返回值可以忽略&…

麒麟龙芯loongarch64 electron 打包deb包

在麒麟龙芯&#xff08;loongarch64&#xff09;电脑上 使用electron 开发桌面应用。之前用electron-packager 打包出来的是文件夹 是 unpack 包。现在需要打包deb包&#xff0c;依据开发指南开始打包。 在项目文件夹下 打开终端 输入 npm run packager 先打包unpack包 然后…

FreeRTOS:3.消息队列

FreeRTOS消息队列 本文主要基于消息队列的源码进行分析&#xff0c;来对FreeRTOS的消息队列进一步学习。 消息队列非常重要&#xff0c;因为后面的各种信号量基本都是基于队列的&#xff0c;搞清楚消息队列的源码&#xff0c;也就搞清楚消息队列的原理。 参考链接&#xff1…

188页 | 2023企业数字化转型建设方案(数据中台、业务中台、AI中台)(免费下载)

1、知识星球下载&#xff1a; 如需下载完整PPTX可编辑源文件&#xff0c;请前往星球获取&#xff1a;https://t.zsxq.com/19KcxSeyA 2、免费领取步骤&#xff1a; 【1】关注公众号 方案驿站 【2】私信发送 【2023企业数字化转型建设方案】 【3】获取本方案PDF下载链接&#…

AI:165-Coze自定义赛博风格Bot-图片生成操作指南

Coze是由字节跳动推出的一个AI聊天机器人和应用程序编辑开发平台&#xff0c;旨在帮助用户快速创建各种类型的聊天机器人、智能体、AI应用和插件&#xff0c;并将其部署在社交平台和即时聊天应用程序中&#xff0c;如Discord、WhatsApp、Twitter、飞书、微信公众号等。 这个平…

计算机网络3——数据链路层3以太网的MAC层

文章目录 一、MAC 层的硬件地址1、介绍2、注意点3、定制标准 二、MAC 帧的格式1、结构2、工作原理3、其他 一、MAC 层的硬件地址 1、介绍 在局域网中&#xff0c;硬件地址又称为物理地址或 MAC地址(因为这种地址用在MAC帧中)。 大家知道&#xff0c;在所有计算机系统的设计中…

剑指Offer题目笔记32(拓扑排序)

面试题113&#xff1a; 解决方案&#xff1a; 将课程看成图中的节点&#xff0c;如果两门课程存在先修顺序那么它们在图中对应的节点之间存在一条从先修课程到后修课程的边&#xff0c;因此这是一个有向图。可行的修课序列实际上是图的拓扑排序序列。图中的每条边都是从先修课…

C++并发编程

基本介绍 线程 C98标准没有直接提供原生的多线程支持 在C98中&#xff0c;并没有像后来的C11标准中那样的<thread>库或其他直接的多线程工具 然而&#xff0c;这并不意味着在C98中无法实现多线程。开发者通常会使用平台特定的API&#xff08;如Windows的线程API或POSI…

前端开发攻略---用原生JS在网页中也能实现 文本转语音!

1、原理 语音合成 (也被称作是文本转为语音&#xff0c;英语简写是 tts) 包括接收 app 中需要语音合成的文本&#xff0c;再在设备麦克风播放出来这两个过程。 Web API中对此有一个主要控制接口 SpeechSynthesis&#xff0c;外加一些处理如何表示要被合成的文本 (也被称为 utte…

玩转微服务-SonarQube

这里写目录标题 第一节 SonarQube1.1 简介1.2 四个组成部分1.2.1 SonarQube服务器1.2.2 SonarQube数据库1.2.3 插件1.2.4 Scanner 1.3 工作流程 第二节 SonarQube的安装2.1 安装2.2 插件 第三节 P3C规范3.1 简介3.2 SonarQube 配置 P3C规范3.3 IDEA配置 P3C规范 第四节 Maven项…

机器学习-期末复习

本文的内容按照作者的课程考试要求书写&#xff0c;仅供复习参考。&#x1f337;&#x1f337;&#x1f337;欢迎大家指正&#xff01; 机器学习是一种人工智能&#xff08;AI&#xff09;的分支领域&#xff0c;它致力于开发能够通过数据学习和改进的算法和模型。简而言之&…

2024年AIGC+教育行业报告

在宏观层面上&#xff0c;如果把人工智能看作一种生命体&#xff0c;AIGC教育的内涵其实是碳基生命和硅基生命的 交互和培育问题。AIGC技术是对人脑计算、思考、判断等内在能力的延伸&#xff0c;是人的智能在机器形态 上的规模化聚集、运作和反应。由此&#xff0c;部分基础性…

【漏洞复现】云时空社会化商业ERP系统LoginName SQL注入漏洞

漏洞描述&#xff1a; 云时空社会化商业ERP系统loginName存在SQL注入漏洞&#xff0c;攻击者可以通过此漏洞获取数据库敏感信息。 搜索语法: Fofa-Query: app"云时空社会化商业ERP系统" 漏洞详情&#xff1a; 1.云时空社会化商业ERP系统。 2.漏洞POC&#xff1a…

倒计时开始!Big Demo Day第十二期,揭秘DePIN,探索Web3未来(附参会指南)

香港—— 全球领先的 Web3.0 活动 Big Demo Day 第十二期即将于 4 月 26 日在香港数码港盛大举行。本次活动由知名科技企业 ZeeprLabs 赞助&#xff0c;Central Research 主办&#xff0c;并得到 Techub News 的联合主办以及数码港、852Web3 等机构的合作支持。 在过去的 11 期…