import pandas as pd
import numpy as np
import os
# pip install html5lib -i https://pypi.tuna.tsinghua.edu.cn/simple/
#创建DataFrame
np.random.seed(10)
# data = np.random.rand(3,10)
# data = np.random.randint(3,10,(5,3))
pd.DataFrame(data,
index=pd.date_range(start='2022-07-22',periods=data.shape[0]),
columns=np.random.choice(['住房','医疗','餐饮','洗浴','教育'],size=data.shape[1]))
# list1=[df,0]
# list1
|
住房 |
餐饮 |
住房 |
2022-07-22 |
4 |
8 |
7 |
2022-07-23 |
3 |
4 |
6 |
2022-07-24 |
7 |
4 |
8 |
2022-07-25 |
3 |
8 |
4 |
2022-07-26 |
5 |
3 |
4 |
#从你的粘贴板获取内容,并传给read_table()
# pd.read_clipboard()
# 温馨提示:并不是所有表格都可以用read_html()来抓取,有的网站表面上看起来是表格,但在网页源代码中不是table格式,而是list列表格式。这种表格则不适用read_html爬取,得用其他的方法,比如selenium
# 传入要抓取的url
SinaFund_url = "http://vip.stock.finance.sina.com.cn/q/go.php/vComStockHold/kind/jjzc/index.phtml?p="
#0表示选中网页中的第一个Table,或者这么使用pd.read_html(url, header=0, index_col=0,encoding = "gbk")
df = pd.read_html(SinaFund_url)[0]
# 打印预览
df.index = pd.date_range('2022/07/22', periods=df.shape[0])
df
|
代码 |
简称 |
截至日期 |
家数 |
本期持股数(万股) |
持股占已流通A股比例(%) |
同上期增减(万股) |
持股比例(%) |
上期家数 |
明细 |
2022-07-22 |
600313 |
农发种业 |
2022-06-30 |
2 |
2179.0000 |
2.01 |
-2926.8576 |
4.72 |
3 |
+展开明细 |
2022-07-23 |
600873 |
梅花生物 |
2022-06-30 |
4 |
23737.8315 |
7.66 |
9205.9723 |
4.69 |
2 |
+展开明细 |
2022-07-24 |
838 |
财信发展 |
2022-06-30 |
1 |
455.8100 |
0.41 |
455.8100 |
0.00 |
0 |
+展开明细 |
2022-07-25 |
600976 |
健民集团 |
2022-06-30 |
2 |
748.5647 |
4.88 |
-88.4205 |
5.46 |
3 |
+展开明细 |
2022-07-26 |
2843 |
泰嘉股份 |
2022-06-30 |
2 |
168.4500 |
0.80 |
168.4500 |
0.00 |
0 |
+展开明细 |
2022-07-27 |
300463 |
迈克生物 |
2022-06-30 |
2 |
954.3226 |
1.56 |
-154.0937 |
1.81 |
2 |
+展开明细 |
2022-07-28 |
300702 |
天宇股份 |
2022-06-30 |
4 |
1419.6284 |
4.08 |
-792.9932 |
6.36 |
5 |
+展开明细 |
2022-07-29 |
301025 |
读客文化 |
2022-06-30 |
1 |
47.0200 |
0.12 |
-12.1306 |
0.15 |
2 |
+展开明细 |
2022-07-30 |
603208 |
江山欧派 |
2022-06-30 |
4 |
658.9592 |
6.27 |
-42.6650 |
6.68 |
4 |
+展开明细 |
2022-07-31 |
2865 |
钧达股份 |
2022-06-30 |
3 |
812.6722 |
5.74 |
214.6333 |
4.23 |
1 |
+展开明细 |
2022-08-01 |
300590 |
移为通信 |
2022-06-30 |
3 |
3105.7580 |
6.80 |
271.4101 |
9.31 |
5 |
+展开明细 |
查看、检查数据
#查看头部数据和尾部数据
df.head(3)
df.tail(3)
|
代码 |
简称 |
截至日期 |
家数 |
本期持股数(万股) |
持股占已流通A股比例(%) |
同上期增减(万股) |
持股比例(%) |
上期家数 |
明细 |
2022-07-30 |
603208 |
江山欧派 |
2022-06-30 |
4 |
658.9592 |
6.27 |
-42.6650 |
6.68 |
4 |
+展开明细 |
2022-07-31 |
2865 |
钧达股份 |
2022-06-30 |
3 |
812.6722 |
5.74 |
214.6333 |
4.23 |
1 |
+展开明细 |
2022-08-01 |
300590 |
移为通信 |
2022-06-30 |
3 |
3105.7580 |
6.80 |
271.4101 |
9.31 |
5 |
+展开明细 |
#查看行数和列数
df.shape
(11, 10)
#查看数据类型
df['代码'].dtype
dtype('int64')
# 查看索引、数据类型和内存信息
df.info()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 11 entries, 2022-07-22 to 2022-08-01
Freq: D
Data columns (total 10 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 代码 11 non-null int64
1 简称 11 non-null object
2 截至日期 11 non-null object
3 家数 11 non-null int64
4 本期持股数(万股) 11 non-null float64
5 持股占已流通A股比例(%) 11 non-null float64
6 同上期增减(万股) 11 non-null float64
7 持股比例(%) 11 non-null float64
8 上期家数 11 non-null int64
9 明细 11 non-null object
dtypes: float64(4), int64(3), object(3)
memory usage: 968.0+ bytes
# 查看数值型列的汇总统计 (选择数据类型)
df.describe(include="int64")
|
代码 |
家数 |
上期家数 |
count |
11.000000 |
11.000000 |
11.000000 |
mean |
328608.727273 |
2.545455 |
2.454545 |
std |
249062.753321 |
1.128152 |
1.752920 |
min |
838.000000 |
1.000000 |
0.000000 |
25% |
151664.000000 |
2.000000 |
1.500000 |
50% |
300702.000000 |
2.000000 |
2.000000 |
75% |
600593.000000 |
3.500000 |
3.500000 |
max |
603208.000000 |
4.000000 |
5.000000 |
# 查看Series对象的唯一值和计数
df['简称'].value_counts(dropna=False)
#查看该series的数据结构
df['简称'].value_counts(dropna=False).shape
# 查看该series的索引
df['简称'].value_counts(dropna=False).index
Index(['农发种业', '梅花生物', '财信发展', '健民集团', '泰嘉股份', '迈克生物', '天宇股份', '读客文化', '江山欧派',
'钧达股份', '移为通信'],
dtype='object')
数据选取
#series数据选取
# 根据列名,并以Series的形式返回列
df['简称']
# 以DataFrame形式返回多列
df[['代码', '简称']]
# 按位置选取数据(行:列)
df['简称'].iloc[0]
# 按索引选取数据
df['简称'].loc['2022-07-22']
'农发种业'
# iloc 按数值
# 返回第一行
df.iloc[0,:]
# 返回第一列
df.iloc[:,0]
# 返回第一列的第一个元素
df.iloc[0,0]
#loc 标签
# 返回第一行
df.loc['2022-07-22',:]
# 返回第一列
df.loc[:,'代码']
# 返回第一列的第一个元素
df.loc['2022-07-22','代码']
# 返回第一行的代码列到家数列
df.loc['2022-07-22','代码':'家数']
代码 600313
简称 农发种业
截至日期 2022-06-30
家数 2
Name: 2022-07-22 00:00:00, dtype: object
数据清理
np.random.seed(9)
df = pd.DataFrame(np.random.randint(5,10,(5,3)))
df
|
0 |
1 |
2 |
0 |
9 |
5 |
8 |
1 |
6 |
9 |
8 |
2 |
5 |
7 |
6 |
3 |
5 |
8 |
6 |
4 |
9 |
5 |
9 |
# 强制重命名列名
df.columns = ['a','b','c']
# 批量更改列名
df.rename(columns=lambda x: x + 's')
# 选择性更改列名{'old_name': 'new_ name'}
df.rename(columns={'a': 'aa'})
# 检查DataFrame对象中的空值,并返回一个Boolean数组
pd.isnull(df)
# 检查DataFrame对象中的非空值,并返回一个Boolean数组
pd.notnull(df)
|
a |
b |
c |
0 |
True |
True |
True |
1 |
True |
True |
True |
2 |
True |
True |
True |
3 |
True |
True |
True |
4 |
True |
True |
True |
# 删除所有包含空值的行 可选参数默认集:axis=0,how='any',thresh=None,subset= None,inplace= False,
df.dropna()
# 删除所有包含空值的列
df.dropna(axis=1)
# thresh:删除所有小于n个非空值的行 ????
df.dropna(axis=1,thresh=2)
#填充空值
df.fillna(-9999)
|
a |
b |
c |
0 |
9 |
5 |
8 |
1 |
6 |
9 |
8 |
2 |
5 |
7 |
6 |
3 |
5 |
8 |
6 |
4 |
9 |
5 |
9 |
# 更改Series数据类型
df['a'].astype(int)
# Series或DataFrame替换值 (to_replace,value)
df['a'].replace(9,-991)
df.replace(9,-991)
# Series替换多个值
df['a'].replace([8,6],[-8,-6])
df.replace([8,6],[-8,-6])
|
a |
b |
c |
0 |
9 |
5 |
-8 |
1 |
-6 |
9 |
-8 |
2 |
5 |
7 |
-6 |
3 |
5 |
-8 |
-6 |
4 |
9 |
5 |
9 |
# 更改索引列
df.set_index('a')
# 批量重命名索引
df.rename(index=lambda x: x * 10)
# 批量重命名列
df.rename(columns=lambda x: x + 's')
|
as |
bs |
cs |
0 |
9 |
5 |
8 |
1 |
6 |
9 |
8 |
2 |
5 |
7 |
6 |
3 |
5 |
8 |
6 |
4 |
9 |
5 |
9 |
数据处理:Filter、Sort和GroupBy
# 选择col列的值大于0.5的行
df[df['a'] > 7]
# 按照列col1排序数据,默认升序排列
df.sort_values('a')
# 按照列col1降序排列数据
df.sort_values('a', ascending=False)
# 先按列col1升序排列,后按col2降序排列数据
df.sort_values(['a','b','c'], ascending=[True,False,False])
|
a |
b |
c |
3 |
5 |
8 |
6 |
2 |
5 |
7 |
6 |
1 |
6 |
9 |
8 |
4 |
9 |
5 |
9 |
0 |
9 |
5 |
8 |
# 返回一个按列col进行分组的Groupby对象
df.groupby('a')['b'].sum()
# 返回一个按多列进行分组的Groupby对象 列表[多个列]
df.groupby('a')[['b','c']].sum()
# 返回按列col1分组的 所有列 的均值 默认所有列
df.groupby('a').agg(np.mean)
#字典形式对多个列进行操作
df.groupby('a').agg({'b':np.mean,'c':sum})
|
b |
c |
a |
|
|
5 |
7.5 |
12 |
6 |
9.0 |
8 |
9 |
5.0 |
17 |
# 创建一个按列col1进行分组,并计算col2和col3的最大值的数据透视表 aggfunc= sum,max,avg,np.mean ...
df.pivot_table(index='a', values=['b','c'], aggfunc= np.mean)
|
b |
c |
a |
|
|
5 |
7.5 |
6.0 |
6 |
9.0 |
8.0 |
9 |
5.0 |
8.5 |
# 对DataFrame中的每一列应用函数np.mean 可以是任何函数
df.apply(np.mean)
# 对DataFrame中的每一行应用函数np.max
df.apply(np.max,axis=1)
0 9
1 9
2 7
3 8
4 9
dtype: int32
数据合并
df_a0 = pd.DataFrame(np.random.randint(10,100,(2,3)),columns=df.columns)
df_a0
|
a |
b |
c |
0 |
69 |
98 |
84 |
1 |
66 |
72 |
22 |
df_a1 = pd.DataFrame(np.random.randint(10,100,(5,2)),index=df.index)
df_a1
|
0 |
1 |
0 |
28 |
96 |
1 |
66 |
11 |
2 |
66 |
21 |
3 |
47 |
29 |
4 |
19 |
90 |
# 将df2中的行添加到df1的尾部
pd.concat([df, df_a0]).reset_index(inplace=True)
# 将df2中的列添加到df1的尾部
pd.concat([df, df_a1],axis=1)
|
a |
b |
c |
0 |
1 |
0 |
9 |
5 |
8 |
28 |
96 |
1 |
6 |
9 |
8 |
66 |
11 |
2 |
5 |
7 |
6 |
66 |
21 |
3 |
5 |
8 |
6 |
47 |
29 |
4 |
9 |
5 |
9 |
19 |
90 |
df_m = pd.DataFrame(np.random.randint(1,10,(2,3)),columns=df.columns)
print(df)
df_m
a b c
0 9 5 8
1 6 9 8
2 5 7 6
3 5 8 6
4 9 5 9
# 对df1的列和df2的列执行SQL形式的join
# 参数suffixes是重叠列添加内容
pd.merge(df,df_m,how='inner',on=['a'],suffixes=['_l','_r'])
|
a |
b_l |
c_l |
b_r |
c_r |
0 |
9 |
5 |
8 |
2 |
9 |
1 |
9 |
5 |
9 |
2 |
9 |
数据统计
# 查看数据值列的汇总统计
df.describe()
# 返回所有列的均值
df.mean()
# 返回列与列之间的相关系数
df.corr()
# 返回每一列中的非空值的个数
df.count()
# 返回每一列的最大值
df.max()
# 返回每一列的最小值
df.min()
# 返回每一列的中位数
df.median()
# 返回每一列的标准差
df.std()
a 2.049390
b 1.788854
c 1.341641
dtype: float64