Pandas库相关用法总结【万字梳理,用法描述+代码示例结果(1)

九、数据的自定义处理函数:apply()函数的应用

十、数据的合并与重排序:merge()函数的应用

十一、all()、any()、isin()方法

十二、value_counts()函数的应用

12.1 基础用法

12.2 衍生用法

十三、格式化输出dataframe

十四、结语


一、前言

作为一名运筹优化算法小白,在实习期间主要基于python语言开发一个自动化智能排程项目的算法,在开发定制化的元启发式算法过程中,数据预处理与清洗、数学模型的抽象化以及调用OR-tools求解器建模占了大头。而在使用pandas库处理数据过程中,一开始用的时候要么忘记对应的用法,要么理解错误某些方法和对象的底层运行逻辑,也是因为自己的不熟练,走了贼多弯路,写代码半小时,小问题debug代码花半天。最近算法部署上线稳定后,也想抽空来梳理梳理常用的pandas库用法以及遇到的小坑,希望看到的小伙伴能少走些弯路。

注:1)下文仅零散记录自己在编算法过程中用到的一些pandas库用法,若要系统的学习pandas库的使用语法,请自行查阅其他参考资料和相关书籍;2)本文的阅读需要读者熟悉python的基础语法,以及对numpy、series以及dataframe等数据类型有一定了解,没了解过的小伙伴可以先自行查阅资料学习相关的概念和定义声明方式。


二、数据读取与导出

在解决实际问题过程中,一个问题的相关信息大多可以整理成excel格式宽表信息,每一行代表某个需要决策的元素(如TSP问题中的一个客户点),每一列即该决策元素相关信息(如客户点坐标,需求等等)。而在编程建模前,往往就需要读取这些宽表信息,并将其中的信息抽象为数学模型的中的矩阵形式,进而开展建模编程,以下给出了python读取excel和导出excel的相关用法,其中hdf5是一类高维的数据存储格式,在此不作详细介绍,有兴趣的小伙伴可自行学习。

input_Data1 = pd.read_excel()  # 从 Excel 文件中读取数据,括号中填写文件路径,只有文件名时,默认读取当前py文件所在路径中的指定文件,若不存在则会报错
input_Data2 = pd.read_hdf()    # 从hdf格式的文件读取数据--需要引入第三方库 pip install tables,入参包括:1)hdf5文件所在路径,2)hdf5文件下存放具体数据的路径 
output_Data.to_csv()           # 将数据写入 CSV 文件,入参中填写文件路径,文件名称,没有文件路径时,默认导出到和当前py文件相同路径下的文件夹
output_Data.to_excel()         # 将数据写入 Excel 文件--需要引入第三方依赖库:pip install openpyxl xlrd xlsxwriter

# 导出文件具体例子:将文件名为“test_data_improve”的dataframe数据对象导出到当前.py文件同目录下,导出的excel中,不展示每一行数据在dataframe中的行索引
test_data_improve.to_excel("test_data_improve.xlsx",index=False)

# 读取文件具体例子:从当前.py文件同目录下读取文件名为“temp_data4.xls”的excel文件,并定义为test_data
test_data = pd.read_excel('temp_data4.xlsx')

# 读取高维数据文件hdf5中某个路径下存放的excel文件
raw_data = pd.read_hdf(algo_data.store, algo_data.raw_data)
  • to_excel() 的括号中通常传入2个参数,即:1)文件导出路径(包含文件名);2)index=True/False,其中index=True,代表导出的文件展示数据的行索引号,index=False代表不展示,即下面图片中红框框出来的第一列索引值。
  • 默认导出路径为主程序py文件所在的目录,当需要修改导出文件的路径时,笔者习惯性地封装了如下的简单函数来方便dataframe对象的输出
def output_data(algo_path, data, file_name):
    '''
    将算法过程中的输出结果,默认存放到指定的临时文件夹中
    :param algo_data: 路径
    :param data: 导出数据
    :param file_name: 导出的文件名
    :return:
    '''
    store_path = os.path.join(algo_path, file_name)
    data.to_excel(store_path, index=False)

  • read_excel()默认读取当前py文件所在同目录下的文件,若文件不存在,则会报错,若需要读取不同目录下的文件,则需要在文件名前增加对应的路径,此时可以封装一个如下函数来读取某个路径下某个文件名的excel文件
def read_data(algo_path, file_name):
    '''
    读取指定路径下的excel文件,并返回dataframe
    :param algo_path:文件所在的路径
    :param file_name:文件名称
    :return:
    '''
    store_path = os.path.join(algo_path, file_name)  # 将路径和文件名相连,形成读取路径入参
    df = pd.read_excel(store_path)                   # 读取对应路径下的对应文件
    return df    

Note:>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

  • 1)执行带有to_excel()的程序时,在导出路径下,与导出对象同名称的.xlsx文件不能开着。
  • 2)执行read_excel()函数时,对源文件不作修改的情况下,调试时打开文件不影响程序执行。

三、数据概要信息

将excel中的信息转化为dataframe数据结构后,我们可以使用如下的方法来快速获得该数据列表的相关摘要信息。

data = pd.read_excel("input_data.xlsx")  # 读取excel数据
data.head()   # 查看数据框的前几行,默认为5行,括号中为查看数据的行数
data.tail()   # 查看数据框的后几行,默认为5行,括号中为查看数据的行数
data.shape    # 获取数据框的行数和列数,得到一个包含行数和列数的元组
data.shape[0] # 获取该表的总行数,不包括列头的那一行
data.shape[1] # 获取该表的总列数,不包括行索引的那一列
data.describe() # 生成数据的统计摘要信息
data.info()   # 显示数据框的基本信息

四、数据清洗和预处理

为甲方开发智能决策系统时,算法的输入数据往往来自于客户业务系统的数据库,其中不免存在一些“脏数据”:譬如某一列的字段数据类型与预期不一致,某一列必填字段存在缺失值,这些脏数据的存在很有可能会导致后续的代码运行报错,因此最好在算法开发之前,建立数据清洗的预处理模块,将导入的源数据(raw_data)转变为算法开发过程中便于检索的基础数据(basic_data)。此外为方便算法开发,往往也需要修改导入数据的列名,或截取其中的部分列名字段即可(譬如笔者拿到的基础视图有将近上百列业务字段,但实际可能只需要其中二十多列的字段)。

针对上述应用背景,笔者在数据清洗和预处理环节主要用到的一些函数和使用方法如下,供读者参考~

4.1 修改某列的数据类型并处理缺失值

  • 利用.astype()方法统一某一列字段的数据类型,防止后续出现数据类型报错
  • 转化为float后,可以将空值替换为’0’或者空字符串,可作为缺失值处理的一种简便方式
  • 若不进行上述方式处理时,当dataframe是由.xlsx文件导入时,空值将被dataframe默认处理为"nan/NAN",极有可能对后续的数据统计和处理带来影响
# 示例一:
temp_data['columnA']= temp_data['columnA'].astype(float)   # 将对应的列均专转化float格式
temp_data['columnA']= temp_data['columnA'].str.replace(' ', "0")  # 将空值转化为字符串“0”

# 示例二:
temp_data['备注'] = temp_data['备注'].astype(str).fillna('')

4.2 删除列/行数据

(1)根据自定义条件删除对应的行数据

  • 删除A列值=T1,B列值=SG4的行向量数据
  • 为了让原表发生更改,下文的代码将删除后的结果重新赋值给原表。如果不希望改变原表,可以将删除后的结果赋值给一个新的变量
  • 使用.drop()函数时,不改变源对象(只是生成一个副本对象,不进行原地修改)
data = data.drop(data2[(data2['A'] == "T1") & (data2['B'] == "SG4")].index)  

(2)根据列名删除列数据

  • 删除原来dataframe对象中,列名=columnA的那列数据
  • 删除列数据时,需要指定axis=1,表示对列向量进行删除
df = df.drop('columnA', axis=1)

4.3 判断某一列是否存在缺省值

  • 使用.isnull()/.isna()与.any()函数来快速判断某一列是否存在空值
import pandas as pd
# 创建一个DataFrame
data = {'A': [1, 2, 3, None, 5],
        'B': ['a', 'b', 'c', 'd', 'e']}
df = pd.DataFrame(data)

# 判断列'A'是否存在空值,或采用df['A'].isna().any()
if df['A'].isnull().any():
    print("列'A'存在空值")
else:
    print("列'A'不存在空值")

4.4 预处理列数据字段,并修改某一列的所在位置

(1)读取指定列的数据并作列名转换

  • 由于业务系统中源data的列名字段过多,当我们开发算法过程中发现仅需要提取其中某些列的数据时,可采用如下方式进行指定列的提取和列名字段的映射转换:
  • 笔者建议new_columns这类涉及到业务字段与算法开发字段进行字段名映射关系的内容,可以单独写到一个json文件中进行维护,方便对接接口开发的同事参考或自己进行日常维护改动。
name_list = ['A','B','C','D','E','F']
temp_data = temp_data[name_list]                     # 只提取指定列
new_columns = {'A':"姓名",'B':"年龄",'C':"性别",'D':"身高",'E':"体重",'F':"学历"}
temp_data.rename(columns=new_columns, inplace=True)  # 进行列名字段的转换

(2)修改某一列的排序位置

  • 作为一名强迫症患者,笔者在数据处理过程中,偶尔希望某个字段排在某个字段前/后,方便在输出该dataframe时,易于人工审查算法的求解结果,故笔者封装了如下的函数特用于某一列的位置转变,供小伙伴们参考~
  • Note:如果想一开始就对源列表的字段名排列顺序,只需要在上文的name_list中将需要用到的列名按照指定的顺序进行排列即可
def change_column_location(input_data,change_demand):
    '''
    改变给定dataframe中,某一列数据的所在位置,将指定列插入到第change_idx之前
    :param input_data: 给定的原始数据
    :param change_demand: 传入一个dict,key为需要改变的列名字段,value为插入的列索引
    :return:
    '''
    for column_name,change_idx in change_demand.items():
        first_column = input_data.pop(column_name)
        input_data.insert(change_idx, column_name, first_column)
    return input_data

五、dict、series以及dataframe三者之间的转换

笔者在使用pandas库对数据进行预处理、分析、统计、排序等操作的过程中,各类操作返回的对象或需要生成的对象基本在dict、series以及dataframe这类对象直接进行转换,刚开始按照算法设计框架进行数据处理和代码层面的问题抽象时,时常因搞混当前新赋值对象是什么类型而出bug,亦或将dict/series的对象合并到dataframe中而出错,在经历过一段时间的尝试和试错后,也有了一些理解和体会。

5.1 dict/series/dataframe的数据形式

为便于读者理解和区分三类数据对象,笔者将其特点总结如下:

  • dict:以{key:value}形式存储的键-值对,可直接通过 对象[键值] 的方式来索引值
  • series: 本质以[{key1:value1},{key2:value2},…]  (附带属性name=column,代表该列值索引的内容) 的形式存储一系列的键值对,同样可通过 **对象[键]**来索引值,但与dict不同的是,series的键往往为行索引/行标签,属于一维数据。
  • dataframe:本质上是将一系列的series进行拼接,按照相同的key值进行了组合,形成类似于[{key1:[value1,value2,…],{key2:[value11,value22,…]},{key3:[value111,value222,value333,…]},…],其中key1,key2,key3 可以视作一份excel中的列A,列B,列C,[value1,value2,…]即代表列A这一列的值
  • 上述举例中,key和value均指代某一个元素的属性和对应的值,而单个key对应多个value值则指代一个行向量,即 key1:[value1,value2,…] 的形式
  • 为了说明dict、series以及dataframe的数据区别和转化过程,笔者基于如下的例子进行示意
# dict格式对象,此时key为列名,value为列向量值
column1 = {'A': [1, 2, 3, 4, 5]}
column2 = {'B': ['a', 'b', 'c', 'd', 'e']}
column3 = {'C': [0.5,0.4,0.6,0.7,1.0]}
# dict格式对象,此时key为列名,value为向量值
test_dict = {'姓名':"nancy",'年龄':26,"身高":100,'体重':150,'性别':"男",}

# series格式对象
series1 = pd.Series([1, 2, 3, 4, 5], name='A')
series2 = pd.Series(['a', 'b', 'c', 'd', 'e'], name='B')
series3 = pd.Series([0.5, 0.4, 0.6, 0.7, 1.0], name='C')
test_ser = pd.Series(test_dict)
print(series1)
print(test_ser)

# dataframe格式对象
c1 = pd.DataFrame(column1)
c2 = pd.DataFrame(column2)
c3 = pd.DataFrame(column3)
df = pd.concat([c1,c2,c3])
test_df = pd.DataFrame(test_ser).T
print(df)
print(test_df)

# 从dataframe取出其中第一行数据
temp_series1= df.iloc[0]
print(temp_series1)

# 从dataframe取出其中第一列数据
temp_series2 = df1.iloc[:,0]       # 方法一获取第一列
temp_series2  = df1.loc[:, 'A']    # 方法二获取第一列
print(temp_series2)

代码的运行结果如下,可以得出以下几点结论:

  • series的行标签既可以为int类型,也可以为str(即列名的key值)
  • 无论从dataframe获取一列还是一行的数据,返回对象均为series,但对应Name属性不相同
  • 从dataframe获取一列数据时,需要用行的整数位置来索引对应的数据;而当获取一行数据时,则使用列名来索引对应的数据,此时用法等价于一个dict对象。
# series格式输出
0    1
1    2
2    3
3    4
4    5
Name: A, dtype: int64   # 注意此时使用 series1[] 来索引值时,只能使用int类型的行索引来取值

姓名    nancy
年龄       26
身高      100
体重      150
性别       男    
dtype: object           # 此时使用 test_ser[] 来索引值时,可直接使用[key值]的方式来索引取值

# dataframe格式输出
   A  B    C
0  1  a  0.5
1  2  b  0.4
2  3  c  0.6
3  4  d  0.7
4  5  e  1.0

    姓名 年龄 身高 体重 性别
0  nancy   26  100  150   男

# 从dataframe取出其中的第一行数据--series对象,Name=0(行索引),行标签为原来dataframe的列名
A      1
B      a
C    0.5
Name: 0, dtype: object

# 从dataframe取出其中的第一列数据--series对象,Name=‘A’(列名),行标签为原来dataframe的行索引
0    1
1    2
2    3
3    4
4    5
Name: A, dtype: int64

5.2 三种类型之间的转换方式

(1)将多个dict,合并到一个dataframe对象中

column1 = {'A': [1, 2, 3, 4, 5]}
column2 = {'B': ['a', 'b', 'c', 'd', 'e']}
column3 = {'C': [0.5, 0.4, 0.6, 0.7, 1.0]}

# 方法一:dict单独转成dataframe后再进行合并
c1 = pd.DataFrame(column1)
c2 = pd.DataFrame(column2)
c3 = pd.DataFrame(column3)
df1 = pd.concat([c1, c2, c3], axis=1)  # 按照列合并
print("df1 如下:\n", df1)


# 方法二:转换为series后,再置于list后进行集中转换
series1 = pd.Series(column1['A'], name='A')
series2 = pd.Series(column2['B'], name='B')
series3 = pd.Series(column3['C'], name='C')
s_list = [series1,series2,series3]
info = []
for i in range(3):
    info.append(s_list[i])
df = pd.DataFrame(info).T
print("df 如下:\n", df)    

代码运行结果如下:

# 方法一输出结果>>>>>>>>>>>>>>>>
df1 如下:
    A  B    C
0  1  a  0.5
1  2  b  0.4
2  3  c  0.6
3  4  d  0.7
4  5  e  1.0
# 方法二输出结果>>>>>>>>>>>>>>>>
df 如下:
    A  B    C
0  1  a  0.5
1  2  b  0.4
2  3  c  0.6
3  4  d  0.7
4  5  e  1.0

(2)将一个dict/series对象合并到一个dataframe对象中(为data添加一行数据)

  • add_row 为一个dict对象,key值与待合并的dataframe对象的列名相同
  • 方法一种:index=[1]代表将给定的dict转化为一个dataframe,其中行向量的行索引属性为1 (可以为任意int值),此时列名为原dict的key值,第一行的数据为对应的value值
  • 方法二中:to_frame()方法将Series对象转换为DataFrame对象,然后transpose()方法对该DataFrame对象进行转置操作,即将行和列进行互换。这样,原本作为Series对象中的数据将被转换为一个行向量,而列名将成为DataFrame的索引。
add_row = {"A": 111, 'B': 'f', 'C': 0.9999}
# 方法一:dict直接转化为dataframe后进行合并
new_df = pd.DataFrame(add_row ,index=[1])     
df1 = pd.concat([df1, new_df])                
print(new_df)
print(df1)

# 方法二:dict转化为series后,再转化为dataframe进行合并
add_row = pd.Series(add_row)
print(add_row)
add_row = add_row.to_frame().transpose()   
# 或者采用 add_row = add_row.to_frame().T
print(add_row)
df1 = pd.concat([df1, add_row])           
print(df1)

代码结果如下:

  • 很显然将dict转化为行数据添加到dataframe使用方法一更直接,此处笔者特意阐述方法二,旨在让读者同时也了解series合并到dataframe中的转换方式
# 方法一运行过程>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# dict直接转化一个dataframe对象
     A  B       C
1  111  f  0.9999

# 将该行数据与原来的dataframe进行合并的结果
     A  B       C
0    1  a    0.50
1    2  b    0.40
2    3  c    0.60
3    4  d    0.70
4    5  e    1.00
1  111  f  0.9999

# 方法二运行过程>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# dict转化为series对象
A       111
B         f
C    0.9999
dtype: object

# series对象再转为dataframe对象
     A  B       C
0  111  f  0.9999

# 最后进行dataframe合并
     A  B       C
0    1  a    0.50
1    2  b    0.40
2    3  c    0.60
3    4  d    0.70
4    5  e    1.00
0  111  f  0.9999

(3)将dataframe转换为dict对象

  • dataframe转换为dict对象本质为提取其中的某一行/或一列数据,其转换过程仍然是通过先得到series对象,再转换为dict对象
  • 从dataframe提取行数据/列数据的方法和介绍详见第六节~
series_obj = df1.iloc[0]     # 取dataframe中的第一行数据,得到的是series,行标签为列名
dict_obj = dict(series_obj)  # series转化为dict,或者使用dict_obj = series_obj.to_dict()
print(dict_obj)

series_obj = df1.iloc[:,0]   # 取dataframe中的第一列数据,得到的是series,行标签为int类型的索引位置
dict_obj = dict(series_obj)  # series转化为dict,或者使用dict_obj = series_obj.to_dict()
print(dict_obj)

代码结果如下:

# 行向量转化为dict的结果,key为列名,value为值
{'A': 1, 'B': 'a', 'C': 0.5}

# 列向量转化为dict的结果,key为行索引,value为值
{0: 1, 1: 2, 2: 3, 3: 4, 4: 5}

六、数据提取、索引与筛选

使用pandas库筛选、分析数据的过程其实和使用office软件去处理excel数据是类似的,其区别主要在于前者将各种需要人工逐步点击的数据筛选、提取、过滤或者计算公式的操作全部通过代码实现了自动化处理。下文给出了笔者在进行数据提取或筛选时常用的一些方法和注意要点。

6.1 iloc[] 按照行/列位置索引获取数据

data.iloc[]常用于按照行/列索引来获取指定行、指定列的数据,得到一个新的dataframe对象或series对象,笔者常用的场景如下:

  • 使用data.iloc[x,y]的方式即可获取dataframe中行索引为x行,列索引y列的某个值
  • 使用data.iloc[x]的方式即可获取dataframe中行索引为x的行数据,返回的是series对象
  • 使用data.iloc[:,y]的方式即可获取dataframe中第y列的列数据,返回的是series对象
  • 使用data.iloc[x:y]的方式即可获取dataframe中行索引从x到y行的数据,返回的仍然为dataframe对象,这一点同列表的切片操作类似,是左闭右开的。
  • 使用data.iloc[[x1,x2]:[y1,y2]]的方式即可获取dataframe中第x1x2行,y1y2列的数据,返回的仍然为dataframe对象,这一点同列表的切片操作类似,是左闭右开的。

注意>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

  • 1)x和y均需要为int类型,否则会报错
  • 2)x和y分别为dataframe中的行索引和列索引,但不完全等价于该数据在整个dataframe中的第x行和第y列(绝对位置),因为行索引index是可以修改的,故处理数据时,一定要注意整个列表的行索引是否是从0开始递增的,通常可以用data.reset_index(drop=True,inplace=True)来重置索引;其中当drop=False时,将自动生成一列(列名=index)用于记录重置索引前每一列数据的行索引
  • 3)iloc[x,y]中的x和y必须是该dataframe内存在的行索引和列索引,否则会出现索引越界报错
data = pd.read_excel("input_data.xlsx")  # 读取excel数据
item1 = data.iloc[0]      # 取该DataFrame的第一行数据,返回对象为series格式,key为对应数据的列明,value为对应的值
item2 = data.iloc[-1]     # 取该DataFrame的最后一行数据,返回对象为series格式,key为对应数据的列明,value为对应的值
item3 = data.iloc[0,0]    # 取该DataFrame中第0行,第0列的数据(其中0行为除列名外的第一行)
data2 = data.iloc[1:5]    # 取该DataFrame中第1行到第4行的数据,生成一份新的数据对应data2

6.2 loc[] 按照行/列标签索引来获取数据

data.loc[row_label,column_label] 方法常用于按照指定“标签”去提取数据,其中的row_labelcolumn_label可以是单个标签、标签列表、布尔数组、切片等,分别用于指定行和指定列的位置;使用loc[]函数时,需要注意传入的行标签和列标签必须存在,否则会报错。具体的用法如下:

import pandas as pd

# 创建一个DataFrame
data = {'Name': ['Alice', 'Bob', 'Charlie', 'David'],
        'Age': [25, 30, 35, 40],
        'Gender': ['F', 'M', 'M', 'M']}
df = pd.DataFrame(data)

# 使用loc[]提取指定行和列的数据
print(df.loc[1, 'Name'])  # 提取第2行,Name列的数据,输出Bob
print(df.loc[1:2, ['Name', 'Age']])  # 提取第2行到第3行,Name和Age列的数据

笔者将自己使用loc[]提取数据的高频场景主要有以下两种,供小伙伴们参考:

1)用法一:批量修改某一字段下,符合指定条件的数据

  • 当需要综合某一列/某几列的值,来改写另一列的值时,可通过如下方式进行批量修改:
# 根据"后工序"列的值,批量修改"集批后工序"列的值
# 底层逻辑为:利用loc[row_label,column_label]提取到对应的“单元格”,然后将其修改为“s1”
temp_data.loc[(temp_data['后工序'] == 'S1'), '集批后工序'] = 's1'

# 根据"后工序"以及"镀层类型代码"列的值,批量修改"集批后工序"列的值
temp_data.loc[(temp_data['后工序'] == 'D1') & (temp_data['镀层类型代码'] == 'ZF'), '集批后工序'] = 'D1-ZF' 

2)用法二:获取符合指定条件的行向量索引

  • 当需要对比两份dataframe,相同元素的行索引是否一致时,可通过如下的方式进行判断:
def compare_sequence(self,algo_plan,formal_plan):
'''
对比algo_plan与formal_plan两份数据,判断其中相同MAT_NO的数据索引是否相同
'''
    task_1 = algo_plan[algo_plan['MAT_NO'].isin(formal_plan['MAT_NO'])]    
    task_2 = formal_plan[formal_plan['MAT_NO'].isin(algo_plan['MAT_NO'])]  
    task_1.reset_index(drop=True,inplace=False)
    task_2.reset_index(drop=True, inplace=False)
    task1_list = list(task_1['MAT_NO'])
    task2_list = list(task_2['MAT_NO'])         
    for i in range(task_1.shape[0]):
        if task1_list[i] != task2_list[i]:
            # 前提:每个元素(每一行数据)的MAT_NO标签是唯一的
            indices = task_2.loc[task_2['MAT_NO'] == task1_list[i]].index[0]
            if i < indices:
                move = ">>>向后移动"
            else:
                move = "<<<向前移动"
    
  • 需要注意的时,使用loc[]方法去提取数据时,通常返回一个dataframe对象,因此使用.index方法时,得到的为一个包含符合条件行的行索引列表(尽管可能只有1个元素),因此还需要用.index[0]的方式来取出所需的行索引

3)用法三:获取指定条件的行数据

  • 用法三与用法二类似,均使用loc[]运算来提取满足指定条件下的dataframe对象
  • 当我们需要基于某个唯一标识字段,去获取另一个dataframe对象中的行数据时,可采用如下的方法来获取到对应的一行数据(series格式)
  • 在如下的代码中,通过data1.loc[]的方式,提取满足指定条件的dataframe对象,再利用iloc[0]的方式获得该dataframe中的首行数据,即可得到对应的series对象
  • 使用该方法时,需要注意另一个被查询的dataframe对象中(data1),待查询标识(“MAT_NO”)必须是唯一的,否则可能无法取到唯一的那行期望数据
 item_i = data1.loc[data1['MAT_NO'] == mat_no2].iloc[0]  # 找到对应的行数据

6.3 使用[]运算符自定义筛选条件获取数据

  • 使用[]方法提取指定条件的数据逻辑同我们使用excel中的“筛选”功能,并且更加的灵活和方便,代码如下:
# ori_data为给定的源数据,假定该数据有“A”、“B”、“C”、“D”列
# A列、B列为int格式,C列、D列为str格式
# 则通过下列语句可以筛选同时满足:1)A列值>=min_thick;2)B列值<=max_thick;3)C列值等于‘value’;4)D列的值属于require_material(列表)
temp_data = ori_data[(ori_data['A'] >= min_thick)
                      & (ori_data['B'] <= max_thick)
                      & (ori_data['C'] == 'value'])
                      & (ori_data['D'].isin(require_materail))]

# 假如我们要提取data的第2、3行和从Price到Sales对应的列 (连续的列,用切片操作)
new_df = data[2:3,'Price':'Sales']

# 假如我们要选取所有的行和Fruits和Sales对应的列
new_df = data[:,'Price':'Sales']

注意>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

  1. []中不同的条件表达式之间,表示“与”逻辑运算使用**“&”连接,表示“或”逻辑运算使用“|”**连接,若使用’and’或’or’会报错
  2. 使用data[‘column’].isin()的方法来筛选对应列中,值属于某几个枚举项的数据
  3. 切片操作与list的切片类似,但使用[]去提取对应行和列的数据时,为左闭右闭区间,同时列名“标签”之间必须是连续的

6.4 数据提取和筛选方法小结

  • iloc[]利用行索引和列索引来提取指定数据,[]中只能为int类型,输入的行列索引之间用“,”分隔
  • loc[]利用行标签和列标签来提取指定数据,[]中可以为标签/布尔判断语句
  • 利用[]来自定义筛选数据的判断条件,并提取源数据的副本数据,且具有切片功能
  • 提取数据和筛选数据可以灵活地结合上述三种方法来使用,但需要注意不同方法返回的对象格式,例如iloc[x]返回的是series,loc[“条件表达式”](仅对行数据进行筛选)返回的是dataframe对象,调试代码时建议多利用type()来确定自己真正得到了什么格式的对象

七、数据统计与排序

7.1 基础信息统计

pandas库中有内置函数可以帮助我们直接统计得到某一列数据的基础统计信息,以及对某列数据进行累计求和,非常便捷!

# 常用的统计方法如下:
data[‘columnA’].sum()   # 求列名为‘columnA’的总和
data[‘columnB’].mean()  # 求列名为‘columnB’的平均值
data[‘columnC’].max()   # 求列名为‘columnC’的最大值
data[‘columnD’].max()   # 求列名为‘columnD’的最小值

假若想要对某一列的数据进行累加求和,可使用cumsum()函数得到某一列值的累计求和值。并通过“[]”运算符对数据按照某个累计值进行截断处理,如下所示:

# 对某列数据进行累加求和统计,并按照指定值进行数据截断
temp_data['重量累计值'] = temp_data['重量'].cumsum()
temp_data['长度累计值'] = temp_data['长度'].cumsum()
temp_data = temp_data[(temp_data['重量累计值'] <= wt_max) & (temp_data['长度累计值'] <= km_max)]

7.2 自定义排序

pandas库中还有内置的排序函数,能够按照指定列,指定排序方式对数据进行快速排序,但需要注意的是,该排序函数分“拷贝排序”和“原地排序”两种情况,区别在于指定的inplace参数是否为True,具体用法如下所示:

  • by=[]中填写的字段顺序代表了排序优先级,即下面代码中先根据x进行降序,在对x列相同值的行数据,按照y值进行降序排序
# 如下展示了两种对数据进行排序的方式,均实现了:将整个表格中的数据按照x,y列的值,进行降序、降序排序

# 第一种排序方式下,源数据并不会改变,而是生成了一个排序后的副本,将其重新赋值给了data
data = data.sort_values(by=['x','y'],ascending=[False,False]) 

# 第二种排序方式下,源数据会发生改变,即进行了原地排序
data.sort_values(by=['x','y'],ascending=[False,False],inplace=True)

# 注意:上述排序完毕后,数据的行索引也会跟着移动改变!

八、数据的聚类统计:groupby()函数的应用

在数据统计和分析过程中,聚类统计/提取数据往往是使用频率最高的处理方法,而pandas库中自带内置函数groupby(),可以帮助我们快速地对整个DataFrame按照某些字段和统计方法进行聚类分组统计,该函数的基础使用语法如下:

  • data.groupby() 对dataframe对象进行分组,此时返回对象格式为“DataFrameGroupBy”
  • 利用[]运算符对指定字段进行同组内的数值统计
  • 当传入的分组标签唯一时,得到的结果为一个series对象,key为分组的枚举值,value为对应分组内的指标统计值;当传入的分组标签为一个[]时,得到的结果为一个dataframe对象
  • 通过上述方式得到的分组统计结果,可使用iloc[]方式逐行进行遍历,但只能得到对应行的统计结果。若需要查询对应的分组标签和分组统计值,建议使用.reset_index()将其转换为dataframe对象,利用iloc[]获得各分组的series对象后,再查询对应的分组标签和分组统计量
# 将源数据根据列“A”进行分组
group_data = data.groupby('A')



**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

**因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
![img](https://img-blog.csdnimg.cn/img_convert/2caed41e39264b9ae44138f02d251a66.png)
![img](https://img-blog.csdnimg.cn/img_convert/57dda72ed47eb0afcd444e9b4d2e122e.png)
![](https://img-blog.csdnimg.cn/img_convert/46506ae54be168b93cf63939786134ca.png)
![](https://img-blog.csdnimg.cn/img_convert/252731a671c1fb70aad5355a2c5eeff0.png)
![](https://img-blog.csdnimg.cn/img_convert/6c361282296f86381401c05e862fe4e9.png) 
![](https://img-blog.csdnimg.cn/img_convert/9f49b566129f47b8a67243c1008edf79.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Python开发知识点,真正体系化!**

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**

**如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注Python)**
![img](https://img-blog.csdnimg.cn/img_convert/435ca3ec9123cd675717c911869a22b1.png)



现在能在网上找到很多很多的学习资源,有免费的也有收费的,当我拿到1套比较全的学习资源之前,我并没着急去看第1节,我而是去审视这套资源是否值得学习,有时候也会去问一些学长的意见,如果可以之后,我会对这套学习资源做1个学习计划,我的学习计划主要包括规划图和学习进度表。



分享给大家这份我薅到的免费视频资料,质量还不错,大家可以跟着学习

![](https://img-blog.csdnimg.cn/img_convert/21b2604bd33c4b6713f686ddd3fe5aff.png)




[**一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!**](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)

**AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算**

本涵盖了95%以上Python开发知识点,真正体系化!**

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**

**如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注Python)**
[外链图片转存中...(img-gXIrhjZJ-1712211061687)]



现在能在网上找到很多很多的学习资源,有免费的也有收费的,当我拿到1套比较全的学习资源之前,我并没着急去看第1节,我而是去审视这套资源是否值得学习,有时候也会去问一些学长的意见,如果可以之后,我会对这套学习资源做1个学习计划,我的学习计划主要包括规划图和学习进度表。



分享给大家这份我薅到的免费视频资料,质量还不错,大家可以跟着学习

![](https://img-blog.csdnimg.cn/img_convert/21b2604bd33c4b6713f686ddd3fe5aff.png)




[**一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!**](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)

**AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算**

  • 24
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准:Go语言的标准非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值