python-数据分析-Pandas-2、DataFrame对象-数据获取

如果使用 pandas 做数据分析,那么DataFrame一定是被使用得最多的类型,它可以用来保存和处理异质的二维数据。
这里所谓的“异质”是指DataFrame中每个列的数据类型不需要相同,这也是它区别于 NumPy 二维数组的地方。
DataFrame提供了极为丰富的属性和方法,帮助我们实现对数据的重塑、清洗、预处理、透视、呈现等一系列操作。
# -*- coding: utf-8 -*-
#DataFrame

import numpy
import pandas

# 1、通过二维数组创建DataFrame对象
scores = numpy.random.randint(60, 101, (5, 3))  # 生成60到100的数组--5行3列
courses = ['语文', '数学', '英语']    # 生成语文、数学、英语的数组
stu_ids = numpy.arange(1001, 1006)  # 生成1001到1005的数组
# 创建DataFrame对象
# data:二维数组,columns:列名,index:行名
df1 = pandas.DataFrame(data=scores, columns=courses, index=stu_ids)
print(df1)
'''
      语文  数学  英语
1001  67  61  82
1002  71  93  81
1003  73  65  74
1004  75  80  71
1005  81  95  71
'''
print('-------------------------------------------')

#通过字典创建DataFrame对象
scores = {
    '语文': [62, 63, 64, 65, 66],
    '数学': [67, 68, 69, 70, 71],
    '英语': [72, 73, 74, 75, 76]
}
stu_ids = numpy.arange(1001, 1006)
df2 = pandas.DataFrame(data=scores, index=stu_ids)
print(df2)
'''
      语文  数学  英语
1001  62  67  72
1002  63  68  73
1003  64  69  74
1004  65  70  75
1005  66  71  76
'''

print('-------------------------------------------')

 通过读取CSV文件创建DataFrame对象

#读取csv文件创建DataFrame对象
#可以通过pandas模块的read_csv函数来读取csv文件、read_csv函数的参数非常多、如下:
"""
sep / delimiter:分隔符,默认是 , 逗号
header:表头(列索引)的位置,默认值是infer,用第一行的内容作为表头(列索引)。
index_col:用作行索引(标签)的列。
usecols:需要加载的列,可以使用序号或者列名。
true_values / false_values:哪些值被视为布尔值True / False。
skiprows:通过行号、索引或函数指定需要跳过的行。
skipfooter:要跳过的末尾行数。
nrows:需要读取的行数。
na_values:哪些值被视为空值。
iterator:设置为True,函数返回迭代器对象。
chunksize:配合上面的参数,设置每次迭代获取的数据体量。
"""

df3 = pandas.read_csv('file/2023年北京积分落户数据.csv', index_col='公示编号')
print(df3)
'''
            姓名     出生年月                 单位名称    积分分值
公示编号                                                
202300001   张浩  1977-02           北京首钢股份有限公司  140.05
202300002   冯云  1982-02        中国人民解放军空军二十三厂  134.29
202300003  王天东  1975-01       中建二局第三建筑工程有限公司  133.63
202300004   陈军  1976-07       中建二局第三建筑工程有限公司  133.29
202300005  樊海瑞  1981-06         中国民生银行股份有限公司  132.46
...        ...      ...                  ...     ...
202305999   曹恰  1983-09           首都师范大学科德学院  109.92
202306000   罗佳  1981-05  厦门方胜众合企业服务有限公司海淀分公司  109.92
202306001  席盛代  1983-06  中国华能集团清洁能源技术研究院有限公司  109.92
202306002  彭芸芸  1981-09       北京汉杰凯德文化传播有限公司  109.92
202306003   张越  1982-01          大爱城投资控股有限公司  109.92

[6003 rows x 4 columns]
'''

读取Excel表格创建DataFrame对象

#读取Excel表格创建DataFrame对象""
#sheet_name:指定读取的sheet页,默认读取第一个sheet页。
df4 = pandas.read_excel('file/2022年股票数据.xlsx', sheet_name='AMZN', index_col='Date')
print(df4)
'''
               Open     High       Low    Close    Volume
Date                                                     
2022-12-30   83.120   84.050   82.4700   84.000  62401194
2022-12-29   82.870   84.550   82.5500   84.180  54995895
2022-12-28   82.800   83.480   81.6900   81.820  58228575
2022-12-27   84.970   85.350   83.0000   83.040  57284035
2022-12-23   83.250   85.780   82.9344   85.250  57433655
...             ...      ...       ...      ...       ...
2022-01-07  163.839  165.243  162.0310  162.554  46605900
2022-01-06  163.450  164.800  161.9370  163.254  51957780
2022-01-05  166.883  167.126  164.3570  164.357  64302720
2022-01-04  170.438  171.400  166.3490  167.522  70725160
2022-01-03  167.550  170.704  166.1600  170.404  63869140

[251 rows x 5 columns]

'''

 

通过读取关系型数据库二维表创建DataFrame对象

pandas模块的read_sql函数可以通过 SQL 语句从数据库中读取数据创建DataFrame对象,该函数的第二个参数代表了需要连接的数据库。

对于 MySQL 数据库,我们可以通过pymysqlmysqlclient来创建数据库连接(需要提前安装好三方库),得到一个Connection 对象,而这个对象就是read_sql函数需要的第二个参数

# -*- coding: utf-8 -*-
#读取关系数据库二维表创建DataFrame对象

import pandas
import pymysql
from sqlalchemy import create_engine

# #方法一:
# #创建一个mysql数据库的连接对象""
# conn = pymysql.connect(
#     host='172.16.8.184',
#     user='root',
#     password='123456',
#     port=3307,
#     database='iamdb',
#     charset='utf8'
# )
# #通过sql从数据库二维表读取数据创建DataFrame
# df5 = pandas.read_sql('select * from sys_user', conn, index_col='id')
# print(df5)

#执行上面的代码会出现一个警告,因为 pandas 库希望我们使用SQLAlchemy三方库接入数据库,
# 具体内容是:“UserWarning: pandas only supports SQLAlchemy connectable (engine/connection) or database string URI or sqlite3 DBAPI2 connection. Other DBAPI2 objects are not tested. Please consider using SQLAlchemy.”。
# 如果不想看到这个警告,我们可以试一试下面的解决方案。



#方法二:(推荐)
#使用SQLAlchemy引擎连接数据库:替换原来的pymysql.connect为create_engine函数创建的引擎。
# URL字符串包含了数据库类型(mysql+pymysql)、用户名、密码、主机地址、端口和数据库名,以及字符集设置
## 创建SQLAlchemy引擎连接MySQL数据
#使用read_sql_query而非read_sql:虽然在这个上下文中两者通常可以互换使用,但明确使用read_sql_query可以更好地表达意图,即执行SQL查询来读取数据
engine = create_engine("mysql+pymysql://root:123456@172.16.8.184:3307/iamdb?charset=utf8")
df6 = pandas.read_sql_query('select * from sys_user', engine, index_col='id')
print(df6)
'''
            created_at          updated_at  ... locked_at regions
id                                          ...                  
1  2023-08-10 10:35:48 2024-02-28 14:25:08  ...      None    None
2  2023-08-10 10:43:00 2024-06-05 16:29:17  ...      None        
3  2023-08-10 10:43:53 2023-10-27 11:11:34  ...      None    None
4  2023-08-10 10:45:12 2023-10-20 09:46:40  ...      None    None
5  2023-08-11 10:38:54 2023-08-11 10:38:54  ...      None    None
..                 ...                 ...  ...       ...     ...
60 2024-03-26 16:07:03 2024-03-26 16:07:54  ...      None    None
61 2024-04-03 14:10:57 2024-05-08 11:53:50  ...      None    深圳地区
62 2024-05-14 15:43:37 2024-05-17 14:54:39  ...      None    广州地区
63 2024-05-21 18:49:18 2024-05-28 10:03:05  ...      None        
64 2024-05-22 17:12:16 2024-05-22 17:12:33  ...      None        

[61 rows x 15 columns]
'''

#我们再来加载特定字段的数据创建DataFrame对象。
df7 = pandas.read_sql_query('select id,username,password,nickname from sys_user', engine, index_col='id')
print(df7)

engine.connect().close()    #关闭连接、释放资源


##说明:如果通过表名加载二维表数据,也可以将上面的函数换成read_sql_table。
df8 = pandas.read_sql_table('sys_user', engine, index_col='id')
print(df8) #获取整个表的数据

DataFrame 的基本属性和方法

属性名 说明
at / iat 通过标签获取DataFrame中的单个值。
columns DataFrame对象列的索引
dtypes DataFrame对象每一列的数据类型
empty DataFrame对象是否为空
loc / iloc 通过标签获取DataFrame中的一组值。
ndim DataFrame对象的维度
shape DataFrame对象的形状(行数和列数)
size DataFrame对象中元素的个数
values DataFrame对象的数据对应的二维数组

先建三个表

#1、部门表 dept_df
CREATE TABLE `dept_df` (
  `dno` int unsigned NOT NULL AUTO_INCREMENT,
  `dname` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `dloc` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  PRIMARY KEY (`dno`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=41 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC

# 2、员工表(emp_df)
CREATE TABLE `emp_df` (
  `eno` int unsigned NOT NULL AUTO_INCREMENT,
  `ename` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `job` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `mgr` float CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `sal` int CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `comm` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `dno` int CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  PRIMARY KEY (`eno`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=7801 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC

# 3、员工表2(emp2_df)
CREATE TABLE `emp2_df` (
  `eno` int unsigned NOT NULL AUTO_INCREMENT,
  `ename` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `job` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `mgr` float CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `sal` int CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `comm` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `dno` int CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  PRIMARY KEY (`eno`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=9901 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC

========================================================
#对应的csv数据
#1、部门表 dept_df
dno,dname,dloc
10,会计部,北京
20,研发部,成都
30,销售部,重庆
40,运维部,深圳

# 2、员工表(emp_df) 
eno,ename,job,mgr,sal,comm,dno
1359,胡一刀,销售员,3344.0,1800,200.0,30
2056,乔峰,分析师,7800.0,5000,1500.0,20
3088,李莫愁,设计师,2056.0,3500,800.0,20
3211,张无忌,程序员,2056.0,3200,NaN,20
3233,丘处机,程序员,2056.0,3400,NaN,20
3244,欧阳锋,程序员,3088.0,3200,NaN,20
3251,张翠山,程序员,2056.0,4000,NaN,20
3344,黄蓉,销售主管,7800.0,3000,800.0,30
3577,杨过,会计,5566.0,2200,NaN,10
3588,朱九真,会计,5566.0,2500,NaN,10
4466,苗人凤,销售员,3344.0,2500,NaN,30
5234,郭靖,出纳,5566.0,2000,NaN,10
5566,宋远桥,会计师,7800.0,4000,1000.0,10
7800,张三丰,总裁,NaN,9000,1200.0,20

#3、员工表2(emp2_df)
eno,ename,job,mgr,sal,comm,dno
9500,张三丰,总裁,NaN,50000,8000,20
9600,王大锤,程序员,9800.0,8000,600,20
9700,张三丰,总裁,NaN,60000,6000,20
9800,骆昊,架构师,7800.0,30000,5000,20
9900,陈小刀,分析师,9800.0,10000,1200,20
# -*- coding: utf-8 -*-
#DataFrame属性和方法
#在开始讲解DataFrame的属性和方法前,我们先从之前提到的hrs数据库中读取三张表的数据,创建出三个DataFrame对象,完整的代码如下所示

import pandas
from sqlalchemy import create_engine

#创建连接
engine = create_engine('mysql+pymysql://root:123456@192.168.177.190:3307/demo?charset=utf8')
dept_df = pandas.read_sql_table('dept_df', con=engine, index_col='dno')
emp_df = pandas.read_sql_table('emp_df', con=engine, index_col='eno')
emp2_df = pandas.read_sql_table('emp2_df', con=engine, index_col='eno')
print(dept_df)
print(emp_df)
print(emp2_df)
#得到的三个DataFrame对象如下所示。
'''
#部门表(dept_df),其中dno是部门的编号,dname和dloc分别是部门的名称和所在地。
    dname dloc
dno           
10    会计部   北京
20    研发部   成都
30    销售部   重庆
40    运维部   深圳

#员工表(emp_df),其中eno是员工编号,ename、job、mgr、sal、comm和dno分别代表员工的姓名、职位、主管编号、月薪、补贴和部门编号。
     ename   job     mgr   sal    comm dno
eno                                       
1359   胡一刀   销售员  3344.0  1800   200.0  30
2056    乔峰   分析师  7800.0  5000  1500.0  20
3088   李莫愁   设计师  2056.0  3500   800.0  20
3211   张无忌   程序员  2056.0  3200     NaN  20
3233   丘处机   程序员  2056.0  3400     NaN  20
3244   欧阳锋   程序员  3088.0  3200     NaN  20
3251   张翠山   程序员  2056.0  4000     NaN  20
3344    黄蓉  销售主管  7800.0  3000   800.0  30
3577    杨过    会计  5566.0  2200     NaN  10
3588   朱九真    会计  5566.0  2500     NaN  10
4466   苗人凤   销售员  3344.0  2500     NaN  30
5234    郭靖    出纳  5566.0  2000     NaN  10
5566   宋远桥   会计师  7800.0  4000  1000.0  10
7800   张三丰    总裁     NaN  9000  1200.0  20

#员工表(emp2_df),跟上面的员工表结构相同,但是保存了不同的员工数据。
     ename  job     mgr    sal  comm dno
eno                                     
9500   张三丰   总裁     NaN  50000  8000  20
9600   王大锤  程序员  9800.0   8000   600  20
9700   张三丰   总裁     NaN  60000  6000  20
9800    骆昊  架构师  7800.0  30000  5000  20
9900   陈小刀  分析师  9800.0  10000  1200  20
'''

# 1、info() 方法
# info() 方法用于显示DataFrame对象的基本信息,包括行数、列数、列名、列类型、非空行数等。
print(emp_df.info())
'''
<class 'pandas.core.frame.DataFrame'>
Index: 14 entries, 1359 to 7800
Data columns (total 6 columns):
 #   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
 0   ename   14 non-null     object
 1   job     14 non-null     object
 2   mgr     14 non-null     object
 3   sal     14 non-null     object
 4   comm    14 non-null     object
 5   dno     14 non-null     object
dtypes: object(6)
memory usage: 784.0+ bytes
None
'''
print('--------------------------------------------')
# 2、head() 查看DataFrame头部的数据、默认查看前5行的数据
print(emp_df.head())

# 3、tail() 查看DataFrame尾部的数据、默认查看后5行的数据
print(emp_df.tail())

print('--------------------------------------------')

# 4、操作数据
#索引和切片
#获取DataFrame的某一列、如取出emp_df的ename列:两种方法
print(emp_df['ename'])
print(emp_df.ename)
#执行上面的代码可以发现,我们获得的是一个Series对象(包含数据和索引-索引可自定义也可默认)、获得的是eno列和ename 两列的数据。

print('--------------------------------------------')
# 5、获取DataFrame的某一行
#可以使用整数索引或我们设置的索引,例如取出员工编号为2056的员工数据
# loc[2056]表示获取员工编号为2056的员工数据
print(emp_df.loc[2056])
# iloc[1]表示获取第2行数据,iloc[0]表示获取第1行数据,iloc[1:3]表示获取第2行到第3行数据,iloc[1:3, 1:3]表示获取第2行到第3行,第2列到第3列的数据。
#print(emp_df.iloc[1])

#通过执行上面的代码我们发现,单独取DataFrame 的某一行或某一列得到的都是Series对象
print('--------------------------------------------')
# 6、通过花式索引来获取多个行或多个列的数据,花式索引的结果仍然是一个DataFrame对象
#获取多个列:
print(emp_df[['ename', 'job']])
#获取多个行:
print(emp_df.loc[[2056, 7800, 3344]])

print('--------------------------------------------')

# 7、获取或修改DataFrame 对象某个单元格的数据,需要同时指定行和列的索引,例如要获取员工编号为2056的员工的职位信息,
print(emp_df['job'][2056])  #分析师
print(emp_df.loc[2056, 'job'])  #推荐使用这种、因为它只做了一次索引运算        分析师
print(emp_df.loc[2056]['job'])  #分析师

#将该员工的职位修改为“架构师”
emp_df.loc[2056, 'job'] = '架构师'
print(emp_df.loc[2056, 'job'])

print('--------------------------------------------')

#数据筛选
#通过布尔索引对DataFrame对象进行数据筛选,例如我们要从emp_df中筛选出月薪超过3500的员工
filtered_emp_df = emp_df[emp_df['sal'] > 3500]
print(filtered_emp_df)
'''
     ename  job     mgr   sal    comm dno
eno                                      
2056    乔峰  架构师  7800.0  5000  1500.0  20
3251   张翠山  程序员  2056.0  4000     NaN  20
5566   宋远桥  会计师  7800.0  4000  1000.0  10
7800   张三丰   总裁     NaN  9000  1200.0  20
'''

print('--------------------------------------------')
#从emp_df中筛选出月薪超过3500且部门编号为20的员工
filtered_emp_df = emp_df[(emp_df.sal > 3500) & (emp_df['dno'] == 20)]
print(filtered_emp_df)
# print(emp_df[(emp_df.sal > 3500) & (emp_df.dno == 20)])
'''
     ename  job     mgr   sal    comm  dno
eno                                       
2056    乔峰  架构师  7800.0  5000  1500.0   20
3251   张翠山  程序员  2056.0  4000     NaN   20
7800   张三丰   总裁     NaN  9000  1200.0   20
'''

print('--------------------------------------------')
#除了使用布尔索引,DataFrame对象的query方法也可以实现数据筛选,query方法的参数是一个字符串,它代表了筛选数据使用的表达式,而且更符合 Python 程序员的使用习惯
filtered_emp_df = emp_df.query('sal > 3500 and dno == 20')
print(filtered_emp_df)
'''
     ename  job     mgr   sal    comm  dno
eno                                       
2056    乔峰  架构师  7800.0  5000  1500.0   20
3251   张翠山  程序员  2056.0  4000     NaN   20
7800   张三丰   总裁     NaN  9000  1200.0   20
'''

iloc 与 loc 的区别

.loc 和 .iloc 的作用
.loc
.loc 是基于标签(标签索引)的选取方式,可以使用行标签和列标签来选取数据。
作用:通过行和列的标签(名字)来访问数据。
语法:emp_df.loc[row_label, column_label]
row_label:行标签,可以是单个标签或列表、切片。
column_label:列标签,可以是单个标签或列表、切片。


.iloc
.iloc 是基于整数位置(位置索引)的选取方式,使用行和列的位置索引来选取数据。
作用:通过行和列的整数位置来访问数据。
语法:emp_df.iloc[row_index, column_index]
row_index:行位置,可以是单个整数或列表、切片。
column_index:列位置,可以是单个整数或列表、切片。

 

posted @ 2024-06-09 22:31  little小新  阅读(49)  评论(0编辑  收藏  举报