pandas官方中文文档:https://www.pypandas.cn/
pandas官网:https://pandas.pydata.org/docs/
类似于一维数组的对象,由一组索引和一组数据组成
import pandas as pd
import numpy as np
#使用列表创建
s1 = pd.Series([1,'a',2,5])
print(s1)
print(s1.index)
print(s1.values)
#指定索引方式创建
s2 = pd.Series([1,'a',2,5],index=['d','b','a','c'])
print(s2)
#字典的方式查询,根据索引
print(s2['a'])
#根据多个索引查询多个值,查询多个值返回的是另一个series
print(s2[['a','b']])
表格型数据结构,每列可以是不同的值类型;既有行索引index,还有列索引columns;可以看做Series组成的字典
dataframe读取一行或者一列返回series,查询多行多列还是会返回dataframe
查看多少行,多少列、类型等基本信息
object可能是列有多个类型值时,比如float的列中有部分空值
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 ymd 365 non-null object
1 bWendu 365 non-null int32
2 yWendu 365 non-null int32
3 tianqi 365 non-null object
4 fengxiang 365 non-null object
5 fengli 365 non-null object
6 aqi 365 non-null int64
7 aqiInfo 365 non-null object
8 aqiLevel 365 non-null int64
一般都是读取excel、csv文件、mysql数据库创建dataframe,也可以从多个字典序列创建
def dataframe_test():
data = {
"state":['1','2','3'],
"year":[2020,2021,2022],
"pop":[1.5,1.6,3.2]
}
df = pd.DataFrame(data)
print(df)
结果:
state year pop
0 1 2020 1.5
1 2 2021 1.6
2 3 2022 3.2
df.columns返回一个index类型对象,df.index返回一个rangeIndex对象,都可以使用for来循环
colums = df.columns
for i in colums:
print(i)
for i in df.index:
print(i)
df.head()/df.head(2)
df.tail()/df.tail(2)
df.sample(10)
df.set_index()
import pandas as pd
df = pd.read_csv('./beijing_tianqi_2018.csv')
print(df.index)
df.set_index('ymd',inplace=True)
print(df.head()
结果
bWendu yWendu tianqi fengxiang fengli aqi aqiInfo aqiLevel
ymd
2018-01-01 3℃ -6℃ 晴~多云 东北风 1-2级 59 良 2
2018-01-02 2℃ -5℃ 阴~多云 东北风 1-2级 49 优 1
2018-01-03 2℃ -5℃ 多云 北风 1-2级 28 优 1
2018-01-04 0℃ -8℃ 阴 东北风 1-2级 28 优 1
2018-01-05 3℃ -6℃ 多云~晴 西北风 1-2级 50 优 1
print(df.dtypes)
df[[‘bWendu’,‘yWendu’]]可以查询出两列的dataFrame
df.loc[0]查询第一行数据
df.loc[1:2]查询第二三行数据
能查询也能覆盖写入
df.loc[:,'bWendu'] = df['bWendu'].str.replace('℃','').astype('int32')
df.loc[:,'yWendu'] = df['yWendu'].str.replace('℃','').astype('int32')
print(df.head())
结果:
bWendu yWendu tianqi fengxiang fengli aqi aqiInfo aqiLevel
ymd
2018-01-01 3 -6 晴~多云 东北风 1-2级 59 良 2
2018-01-02 2 -5 阴~多云 东北风 1-2级 49 优 1
2018-01-03 2 -5 多云 北风 1-2级 28 优 1
2018-01-04 0 -8 阴 东北风 1-2级 28 优 1
2018-01-05 3 -6 多云~晴 西北风 1-2级 50 优 1
loc第一个参数是index
print(df.loc['2018-01-03',['bWendu']])
print(b['bWendu'])
结果:
bWendu 2
Name: 2018-01-03, dtype: object
2
bWendu 2
yWendu -5
Name: 2018-01-03, dtype: object
print(df.loc[['2018-01-03','2018-01-04','2018-01-05'],'bWendu'])
返回一个series
ymd
2018-01-03 2
2018-01-04 0
2018-01-05 3
Name: bWendu, dtype: int32
print(df.loc[['2018-01-03','2018-01-04','2018-01-05'],['bWendu','yWendu']])
返回个dataframe
bWendu yWendu
ymd
2018-01-03 2 -5
2018-01-04 0 -8
2018-01-05 3 -6
print(df.loc['2018-01-03':'2018-01-05','bWendu'])
返回:
ymd
2018-01-03 2
2018-01-04 0
2018-01-05 3
Name: bWendu, dtype: int32
print(df.loc['2018-01-03','bWendu':'fengxiang'])
返回:
bWendu 2
yWendu -5
tianqi 多云
fengxiang 北风
Name: 2018-01-03, dtype: object
loc第一个参数是bool列表,bool列表长度得等于行数或者列数
print(df.loc[df['yWendu']<-10,:])
结果:
bWendu yWendu tianqi fengxiang fengli aqi aqiInfo aqiLevel
ymd
2018-01-23 -4 -12 晴 西北风 3-4级 31 优 1
2018-01-24 -4 -11 晴 西南风 1-2级 34 优 1
2018-01-25 -3 -11 多云 东北风 1-2级 27 优 1
2018-12-26 -2 -11 晴~多云 东北风 2级 26 优 1
2018-12-27 -5 -12 多云~晴 西北风 3级 48 优 1
2018-12-28 -3 -11 晴 西北风 3级 40 优 1
2018-12-29 -3 -12 晴 西北风 2级 29 优 1
2018-12-30 -2 -11 晴~多云 东北风 1级 31 优 1
布尔表达式的数据样式:
print(df['yWendu']<-10)
结果是365长度的series,和数据行数一样。所以loc是会布尔列表返回True那些行的数据。
ymd
2018-01-01 False
2018-01-02 False
2018-01-03 False
2018-01-04 False
2018-01-05 False
...
2018-12-27 True
2018-12-28 True
2018-12-29 True
2018-12-30 True
2018-12-31 False
Name: yWendu, Length: 365, dtype: bool
Process finished with exit code 0
完美天气=高温小于30、低温大于15、晴天、天气质量优
print(df.loc[(df['bWendu'] < 30) & (df['yWendu']>15) & (df['tianqi'] == '晴') & (df['aqiLevel']==1),:])
结果:
bWendu yWendu tianqi fengxiang fengli aqi aqiInfo aqiLevel
ymd
2018-09-07 27 16 晴 西北风 3-4级 22 优 1
print(df.loc[lambda df:(df['bWendu'] <= 30) & (df['yWendu']>=15) & (df['tianqi'] == '晴') & (df['aqiLevel']==1),:])
结果:
bWendu yWendu tianqi fengxiang fengli aqi aqiInfo aqiLevel
ymd
2018-08-24 30 20 晴 北风 1-2级 40 优 1
2018-09-07 27 16 晴 西北风 3-4级 22 优 1
函数编程的本质:函数自身可以像变量一样传递
def query_data(df):
return df.index.str.startswith('2018-09') & df['aqiLevel']==1
print(df.loc[query_data,:])
返回:
bWendu yWendu tianqi fengxiang fengli aqi aqiInfo aqiLevel
ymd
2018-09-01 27 19 阴~小雨 南风 1-2级 50 优 1
2018-09-04 31 18 晴 西南风 3-4级 24 优 1
2018-09-05 31 19 晴~多云 西南风 3-4级 34 优 1
2018-09-06 27 18 多云~晴 西北风 4-5级 37 优 1
2018-09-07 27 16 晴 西北风 3-4级 22 优 1
2018-09-08 27 15 多云~晴 北风 1-2级 28 优 1
2018-09-13 29 20 多云~阴 南风 1-2级 107 轻度污染 3
2018-09-14 28 19 小雨~多云 南风 1-2级 128 轻度污染 3
2018-09-15 26 15 多云 北风 3-4级 42 优 1
2018-09-16 25 14 多云~晴 北风 1-2级 29 优 1
2018-09-17 27 17 多云~阴 北风 1-2级 37 优 1
2018-09-18 25 17 阴~多云 西南风 1-2级 50 优 1
2018-09-21 25 14 晴 西北风 3-4级 50 优 1
2018-09-22 24 13 晴 西北风 3-4级 28 优 1
2018-09-23 23 12 晴 西北风 4-5级 28 优 1
2018-09-24 23 11 晴 北风 1-2级 28 优 1
2018-09-25 24 12 晴~多云 南风 1-2级 44 优 1
2018-09-29 22 11 晴 北风 3-4级 21 优 1
2018-09-30 19 13 多云 西北风 4-5级 22 优 1
Process finished with exit code 0
修改两列的值
df.loc[:,'bWendu'] = df['bWendu'].str.replace('℃','').astype('int32')
df.loc[:,'yWendu'] = df['yWendu'].str.replace('℃','').astype('int32')
新增一列
df.loc[:,'wencha'] = df['bWendu'] - df['yWendu']
print(df.head())
apply方法,第一个参数是函数,函数返回新列(行)中需要的值;第二个参数axis 0-行 1-列。apply方法返回一个series,可以赋值到行或者列
def get_wendu_type(x):
if x['bWendu'] > 33:
return '高温'
if x['yWendu'] < -10:
return '低温'
return '常温'
df.loc[:,'wendu_type'] = df.apply(get_wendu_type,axis=1)
print(df.head())
#value_counts函数统计一列中每个值的数量
print(df['wendu_type'].value_counts())
结果:
bWendu yWendu tianqi ... aqiLevel wencha wendu_type
ymd ...
2018-01-01 3 -6 晴~多云 ... 2 9 常温
2018-01-02 2 -5 阴~多云 ... 1 7 常温
2018-01-03 2 -5 多云 ... 1 7 常温
2018-01-04 0 -8 阴 ... 1 8 常温
2018-01-05 3 -6 多云~晴 ... 1 9 常温
[5 rows x 10 columns]
常温 328
高温 29
低温 8
Name: wendu_type, dtype: int64
Process finished with exit code 0
def split_column(line):
line["姓名"], line["性别"], line["年龄"], line["籍贯"] = line["数据"].split(":")
return line
df = df.apply(split_column, axis=1)
2.第二种
import pandas as pd
df = pd.read_excel("./c23_excel_vlookup/学生信息表.xlsx")
print(df.head())
def new_columns(row):
newa, newb = row['年龄'] + row['年龄'], row['年龄'] * row['年龄']
return newa, newb
# expand参数会将函数返回的元组拆成两列
df[['newa', 'newb']] = df.apply(new_columns, axis=1, result_type="expand")
print(df.head())
学号 姓名 性别 年龄 籍贯
0 S001 怠涵 女 23 山东
1 S002 婉清 女 25 河南
2 S003 溪榕 女 23 湖北
3 S004 漠涓 女 19 陕西
4 S005 祈博 女 24 山东
学号 姓名 性别 年龄 籍贯 newa newb
0 S001 怠涵 女 23 山东 46 529
1 S002 婉清 女 25 河南 50 625
2 S003 溪榕 女 23 湖北 46 529
3 S004 漠涓 女 19 陕西 38 361
4 S005 祈博 女 24 山东 48 576
Process finished with exit code 0
x是一个行series。assign方法只会新增列(yWendu_huahsi,bWendu_huashi),返回一个新的dataframe,不会修改原df的值
df1 = df.assign(
#摄氏温度转华氏温度
yWendu_huashi = lambda x:x['yWendu'] * 9/5 + 32,
bWendu_huashi = lambda x:x['bWendu'] * 9/5 + 32
)
print(type(df1))
print(df1.head())
结果:
bWendu yWendu tianqi ... wendu_type yWendu_huashi bWendu_huashi
ymd ...
2018-01-01 3 -6 晴~多云 ... 常温 21.2 37.4
2018-01-02 2 -5 阴~多云 ... 常温 23.0 35.6
2018-01-03 2 -5 多云 ... 常温 23.0 35.6
2018-01-04 0 -8 阴 ... 常温 17.6 32.0
2018-01-05 3 -6 多云~晴 ... 常温 21.2 37.4
df['wencha_type'] = ''
df.loc[df['bWendu']-df['yWendu'] > 10,'wencha_type'] = "温差大"
df.loc[df['bWendu']-df['yWendu'] <= 10,'wencha_type'] = "温差正常"
print(df['wencha_type'].value_counts())
一下提取所有数字列统计结果
print(df.describe())
结果:
count-数量、mean-平均值、std-标准差、min-最小值、max-最大值
bWendu yWendu aqi aqiLevel wencha
count 365.000000 365.000000 365.000000 365.000000 365.000000
mean 18.665753 8.358904 82.183562 2.090411 10.306849
std 11.858046 11.755053 51.936159 1.029798 2.781233
min -5.000000 -12.000000 21.000000 1.000000 2.000000
25% 8.000000 -3.000000 46.000000 1.000000 8.000000
50% 21.000000 8.000000 69.000000 2.000000 10.000000
75% 29.000000 19.000000 104.000000 3.000000 12.000000
max 38.000000 27.000000 387.000000 6.000000 18.000000
取中位数
df['a'].median()
print(df['bWendu'].min())
print(df['bWendu'].max())
print(df['bWendu'].mean())
-5
38
18.665753424657535
一般不用于数值列,而是枚举、分类列
print(df['fengxiang'].unique())
print(df['tianqi'].unique())
print(df['fengli'].unique())
['东北风' '北风' '西北风' '西南风' '南风' '东南风' '东风' '西风']
['晴~多云' '阴~多云' '多云' '阴' '多云~晴' '多云~阴' '晴' '阴~小雪' '小雪~多云' '小雨~阴' '小雨~雨夹雪'
'多云~小雨' '小雨~多云' '大雨~小雨' '小雨' '阴~小雨' '多云~雷阵雨' '雷阵雨~多云' '阴~雷阵雨' '雷阵雨'
'雷阵雨~大雨' '中雨~雷阵雨' '小雨~大雨' '暴雨~雷阵雨' '雷阵雨~中雨' '小雨~雷阵雨' '雷阵雨~阴' '中雨~小雨'
'小雨~中雨' '雾~多云' '霾']
['1-2级' '4-5级' '3-4级' '2级' '1级' '3级']
print(df['fengxiang'].value_counts())
南风 92
西南风 64
北风 54
西北风 51
东南风 46
东北风 38
东风 14
西风 6
Name: fengxiang, dtype: int64
用途:
对于X、Y两个变量
print(df.cov())
print(df.corr())
bWendu yWendu aqi aqiLevel wencha
bWendu 140.613247 135.529633 47.462622 0.879204 5.083614
yWendu 135.529633 138.181274 16.186685 0.264165 -2.651641
aqi 47.462622 16.186685 2697.364564 50.749842 31.275937
aqiLevel 0.879204 0.264165 50.749842 1.060485 0.615038
wencha 5.083614 -2.651641 31.275937 0.615038 7.735255
bWendu yWendu aqi aqiLevel wencha
bWendu 1.000000 0.972292 0.077067 0.071999 0.154142
yWendu 0.972292 1.000000 0.026513 0.021822 -0.081106
aqi 0.077067 0.026513 1.000000 0.948883 0.216523
aqiLevel 0.071999 0.021822 0.948883 1.000000 0.214740
wencha 0.154142 -0.081106 0.216523 0.214740 1.000000
print(df['aqi'].corr(df['bWendu']))
print(df['aqi'].corr(df['bWendu']-df['yWendu']))
0.07706705916811069
0.2165225757638205
read_excel方法中skiprows=2表示跳过前两个列(学生信息中前两个为空列)
import pandas as pd
#skiprows=2表示跳过前两个列(学生信息中前两个为空列)
df = pd.read_excel('./student_excel.xlsx',skiprows=2)
print(df)
print(df.isnull())
# 加和处理,False=0 True=1,展示每列有多少缺失值。0就是没有
print(df.isnull().sum())
Unnamed: 0 姓名 科目 分数
0 NaN 小明 语文 85.0
1 NaN NaN 数学 80.0
2 NaN NaN 英语 90.0
3 NaN NaN NaN NaN
4 NaN 小王 语文 85.0
5 NaN NaN 数学 NaN
6 NaN NaN 英语 90.0
7 NaN NaN NaN NaN
8 NaN 小刚 语文 85.0
9 NaN NaN 数学 80.0
10 NaN NaN 英语 90.0
Unnamed: 0 姓名 科目 分数
0 True False False False
1 True True False False
2 True True False False
3 True True True True
4 True False False False
5 True True False True
6 True True False False
7 True True True True
8 True False False False
9 True True False False
10 True True False False
单个列上判断null
print(df['分数'].isnull())
print(df['分数'].notnull())
0 False
1 False
2 False
3 True
4 False
5 True
6 False
7 True
8 False
9 False
10 False
Name: 分数, dtype: bool
1 True
2 True
3 False
4 True
5 False
6 True
7 False
8 True
9 True
10 True
Name: 分数, dtype: bool
结合之前loc函数
print(df.loc[df['分数'].notnull(),:])
打印出了分数不为null的几行数据:
Unnamed: 0 姓名 科目 分数
0 NaN 小明 语文 85.0
1 NaN NaN 数学 80.0
2 NaN NaN 英语 90.0
4 NaN 小王 语文 85.0
6 NaN NaN 英语 90.0
8 NaN 小刚 语文 85.0
9 NaN NaN 数学 80.0
10 NaN NaN 英语 90.0
丢弃掉了全为null的第一列
df.dropna(axis='columns',how='all',inplace=True)
print(df)
姓名 科目 分数
0 小明 语文 85.0
1 NaN 数学 80.0
2 NaN 英语 90.0
3 NaN NaN NaN
4 小王 语文 85.0
5 NaN 数学 NaN
6 NaN 英语 90.0
7 NaN NaN NaN
8 小刚 语文 85.0
9 NaN 数学 80.0
10 NaN 英语 90.0
删除全为空值的行
df.dropna(axis='index',how='all',inplace=True)
print(df)
姓名 科目 分数
0 小明 语文 85.0
1 NaN 数学 80.0
2 NaN 英语 90.0
4 小王 语文 85.0
5 NaN 数学 NaN
6 NaN 英语 90.0
8 小刚 语文 85.0
9 NaN 数学 80.0
10 NaN 英语 90.0
df = df.fillna({'分数':0})
#等同于
df.loc[:,'分数'] = df['分数'].fillna(0)
print(df)
返回个新的dataframe
姓名 科目 分数
0 小明 语文 85.0
1 NaN 数学 80.0
2 NaN 英语 90.0
4 小王 语文 85.0
5 NaN 数学 0.0
6 NaN 英语 90.0
8 小刚 语文 85.0
9 NaN 数学 80.0
10 NaN 英语 90.0
使用空值前面的值填充
df.loc[:,'姓名'] = df['姓名'].fillna(method='ffill')
print(df)
姓名 科目 分数
0 小明 语文 85.0
1 小明 数学 80.0
2 小明 英语 90.0
4 小王 语文 85.0
5 小王 数学 0.0
6 小王 英语 90.0
8 小刚 语文 85.0
9 小刚 数学 80.0
10 小刚 英语 90.0
index=False表示不把自动生成的最左侧的数字列写入到Excel,执行完之后会在当前目录生成一个Excel文件,如果文件已存在会报错。
df.to_excel('./studen_excel_clean.xlsx',index=False)
原因:对dataframe先筛选再set,pandas不能判断这个筛选出的子dataframe是原df的copy还是原df,修改可能会改变原df值,所以报警,修改结果可能会成功。
set的话使用一步搞定,使用loc方法
操作文件:beijing_tianqi_2018.csv
#升序
print(df['aqi'].sort_values())
#降序
print(df['aqi'].sort_values(ascending=False))
print(df.sort_values(by='aqi'))
#默认升序
print(df.sort_values(by=['aqiLevel','bWendu']))
#一升序一降序
print(df.sort_values(by=['aqiLevel','bWendu'],ascending=[True,False]))
str属性只在series上有,dataframe没有str属性和处理方法;str属性只能在字符串列上使用,不能在数字列上使用;str属性和方法是pandas自己封装的一套方法。
df.loc[:,'bWendu'] = df['bWendu'].str.replace('℃','').astype('int32')
print(df['tianqi'].str.len())
print(df.index.str.startswith('2018-09'))
返回布尔类型series
从2018-03-31中提取201803字符串
print(df.index.str.replace('-','').str.slice(0,6))
#或者
print(df.index.str.replace('-','').str[0:6])
s = df['tianqi'].str.replace("[多阴]","")
print(s)
把多、阴两个汉字去掉:
ymd
2018-01-01 晴~云
2018-01-02 ~云
2018-01-03 云
2018-01-04
2018-01-05 云~晴
...
2018-12-27 云~晴
2018-12-28 晴
2018-12-29 晴
2018-12-30 晴~云
2018-12-31 云
Name: tianqi, Length: 365, dtype: object
import pandas as pd
import numpy as np
df = pd.DataFrame(
#arange得到12个数字,然后构建成3行4列的矩阵
np.arange(12).reshape(3,4),
columns=['A','B','C','D']
)
print(df)
A B C D
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
#单列drop,axis=1代表删除某列
df = df.drop('A',axis=1)
print(df)
B C D
0 1 2 3
1 5 6 7
2 9 10 11
#单行drop,axis=0代表删除某行
df = df.drop(1,axis=0)
print(df)
B C D
0 1 2 3
2 9 10 11
反直觉,axis参数指定了行/列,代表行/列要动,未被指定的不动。比如指定了axis=行,那聚合的时候就是行从上到下统计,列不变。
求列平均值
print(df)
r = df.mean(axis=0)
print(r)
A B C D
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
A 4.0
B 5.0
C 6.0
D 7.0
dtype: float64
df.mean(axis=0)代表跨行输出列结果
输出行结果
r = df.mean(axis=1)
print(r)
0 1.5
1 5.5
2 9.5
dtype: float64
def get_sum_value(x):
return x['A'] + x['B'] + x['C'] + x['D']
df['sum_value'] = df.apply(get_sum_value,axis=1)
print(df)
A B C D sum_value
0 0 1 2 3 6
1 4 5 6 7 22
2 8 9 10 11 38
import pandas as pd
df = pd.read_csv("./ratings.csv")
print(df.head())
#set_index方法drop=False表示原结构中还保留userId这一行
df.set_index("userId",inplace=True,drop=False)
print(df.head())
userId movieId rating timestamp
0 1 1 4.0 964982703
1 1 3 4.0 964981247
2 1 6 4.0 964982224
3 1 47 5.0 964983815
4 1 50 5.0 964982931
userId movieId rating timestamp
userId
1 1 1 4.0 964982703
1 1 3 4.0 964981247
1 1 6 4.0 964982224
1 1 47 5.0 964983815
1 1 50 5.0 964982931
index简化查询
print(df.loc[df['userId'] == 500].head())
#等于
print(df.loc[500].head())
userId
500 500 1 4.0 1005527755
500 500 11 1.0 1005528017
500 500 39 1.0 1005527926
500 500 101 1.0 1005527980
500 500 104 4.0 1005528065
print(df.index.is_monotonic_increasing)
print(df.index.is_unique)
df_sorted = df.sort_index()
print(df_sorted.head())
userId movieId rating timestamp
userId
1 1 1 4.0 964982703
1 1 3 4.0 964981247
1 1 6 4.0 964982224
1 1 47 5.0 964983815
1 1 50 5.0 964982931
包括series和dataframe
s1 = pd.Series([1,2,3],index=list('abc'))
s2 = pd.Series([2,3,4],index=list('bcd'))
print(s1)
print(s2)
print(s1+s2)
a 1
b 2
c 3
dtype: int64
b 2
c 3
d 4
dtype: int64
a NaN
b 4.0
c 6.0
d NaN
dtype: float64
Process finished with exit code 0
pd.merge(left,right,how='inner',on=None,left_on=None,right_on=None,left_index=False,right_index_False,sort=True,suffixes=('_x','_y'),copy=True,indicator=False,validate=None)
import pandas as pd
df_ratings = pd.read_csv(
"./movielens-1m/ratings.dat",
sep="::",
engine="python",
names="UserID::MovieID::Rating::Timestamp".split("::")
)
print(df_ratings.head())
df_users = pd.read_csv(
"./movielens-1m/users.dat",
sep="::",
engine="python",
names="UserID::Gender::Age::Occupation::Zip-code".split("::")
)
print(df_users.head())
df_movies = pd.read_csv(
"./movielens-1m/movies.dat",
sep="::",
engine="python",
names="MovieId::Title::Genres".split("::")
)
print(df_movies.head())
UserID MovieID Rating Timestamp
0 1 1193 5 978300760
1 1 661 3 978302109
2 1 914 3 978301968
3 1 3408 4 978300275
4 1 2355 5 978824291
UserID Gender Age Occupation Zip-code
0 1 F 1 10 48067
1 2 M 56 16 70072
2 3 M 25 15 55117
3 4 M 45 7 02460
4 5 M 25 20 55455
MovieId Title Genres
0 1 Toy Story (1995) Animation|Children's|Comedy
1 2 Jumanji (1995) Adventure|Children's|Fantasy
2 3 Grumpier Old Men (1995) Comedy|Romance
3 4 Waiting to Exhale (1995) Comedy|Drama
4 5 Father of the Bride Part II (1995) Comedy
Process finished with exit code 0
df_ratings_users = pd.merge(df_ratings,df_users,left_on="UserID",right_on="UserID",how="inner")
print(df_ratings_users.head())
UserID MovieID Rating Timestamp Gender Age Occupation Zip-code
0 1 1193 5 978300760 F 1 10 48067
1 1 661 3 978302109 F 1 10 48067
2 1 914 3 978301968 F 1 10 48067
3 1 3408 4 978300275 F 1 10 48067
4 1 2355 5 978824291 F 1 10 48067
第二次merge
df_ratings_users_movies = pd.merge(df_ratings_users,df_movies,left_on="MovieID",right_on="MovieId",how="inner")
print(df_ratings_users_movies.head(10))
UserID MovieID ... Title Genres
0 1 1193 ... One Flew Over the Cuckoo's Nest (1975) Drama
1 2 1193 ... One Flew Over the Cuckoo's Nest (1975) Drama
2 12 1193 ... One Flew Over the Cuckoo's Nest (1975) Drama
3 15 1193 ... One Flew Over the Cuckoo's Nest (1975) Drama
4 17 1193 ... One Flew Over the Cuckoo's Nest (1975) Drama
5 18 1193 ... One Flew Over the Cuckoo's Nest (1975) Drama
6 19 1193 ... One Flew Over the Cuckoo's Nest (1975) Drama
7 24 1193 ... One Flew Over the Cuckoo's Nest (1975) Drama
8 28 1193 ... One Flew Over the Cuckoo's Nest (1975) Drama
9 33 1193 ... One Flew Over the Cuckoo's Nest (1975) Drama
[10 rows x 11 columns]
批量合并相同格式的Excel、给DataFrame添加行、给Dataframe添加列
append只有按行合并,没有按列合并,相当于concat按行的简写形式
1、concat合并
df1 = pd.DataFrame({
'A':['A0','A1','A2','A3'],
'B':['B0','B1','B2','B3'],
'C':['C0','C1','C2','C3'],
'D':['D0','D1','D2','D3'],
'E':['E0','E1','E2','E3']
})
df2 = pd.DataFrame({
'A':['A4','A5','A6','A7'],
'B':['B4','B5','B6','B7'],
'C':['C4','C5','C6','C7'],
'D':['D4','D5','D6','D7'],
'F':['F4','F5','F6','F7']
})
print(df1)
print(df2)
df3 = pd.concat([df1,df2])
print(df3)
A B C D E
0 A0 B0 C0 D0 E0
1 A1 B1 C1 D1 E1
2 A2 B2 C2 D2 E2
3 A3 B3 C3 D3 E3
A B C D F
0 A4 B4 C4 D4 F4
1 A5 B5 C5 D5 F5
2 A6 B6 C6 D6 F6
3 A7 B7 C7 D7 F7
A B C D E F
0 A0 B0 C0 D0 E0 NaN
1 A1 B1 C1 D1 E1 NaN
2 A2 B2 C2 D2 E2 NaN
3 A3 B3 C3 D3 E3 NaN
0 A4 B4 C4 D4 NaN F4
1 A5 B5 C5 D5 NaN F5
2 A6 B6 C6 D6 NaN F6
3 A7 B7 C7 D7 NaN F7
2、忽略原来索引:
df3 = pd.concat([df1,df2],ignore_index=True)
print(df3)
A B C D E F
0 A0 B0 C0 D0 E0 NaN
1 A1 B1 C1 D1 E1 NaN
2 A2 B2 C2 D2 E2 NaN
3 A3 B3 C3 D3 E3 NaN
4 A4 B4 C4 D4 NaN F4
5 A5 B5 C5 D5 NaN F5
6 A6 B6 C6 D6 NaN F6
7 A7 B7 C7 D7 NaN F7
3、join=inner过滤掉不匹配的列
df3 = pd.concat([df1,df2],ignore_index=True,join="inner")
print(df3)
A B C D
0 A0 B0 C0 D0
1 A1 B1 C1 D1
2 A2 B2 C2 D2
3 A3 B3 C3 D3
4 A4 B4 C4 D4
5 A5 B5 C5 D5
6 A6 B6 C6 D6
7 A7 B7 C7 D7
4、使用axis=1添加新列
print(df1)
s1 = pd.Series(list(range(4)),name="F")
dff = pd.concat([df1,s1],axis=1)
print(dff)
A B C D E
0 A0 B0 C0 D0 E0
1 A1 B1 C1 D1 E1
2 A2 B2 C2 D2 E2
3 A3 B3 C3 D3 E3
A B C D E F
0 A0 B0 C0 D0 E0 0
1 A1 B1 C1 D1 E1 1
2 A2 B2 C2 D2 E2 2
3 A3 B3 C3 D3 E3 3
4.1、添加多列series
s2 = df1.apply(lambda x:x["A"]+"_GG",axis=1)
print(s2)
s2.name = 'G'
dff = pd.concat([df1,s1,s2],axis=1)
print(dff)
A B C D E F G
0 A0 B0 C0 D0 E0 0 A0_GG
1 A1 B1 C1 D1 E1 1 A1_GG
2 A2 B2 C2 D2 E2 2 A2_GG
3 A3 B3 C3 D3 E3 3 A3_GG
列表中可以只有series,也可以dataframe、series混合
dff = pd.concat([s1,s2],axis=1)
print(dff)
dff = pd.concat([s1,df1,s2],axis=1)
print(dff)
F A B C D E G
0 0 A0 B0 C0 D0 E0 A0_GG
1 1 A1 B1 C1 D1 E1 A1_GG
2 2 A2 B2 C2 D2 E2 A2_GG
3 3 A3 B3 C3 D3 E3 A3_GG
df1 = pd.DataFrame([[1,2],[3,4]],columns=list('AB'))
df2 = pd.DataFrame([[5,6],[7,8]],columns=list('AB'))
print(df1)
print(df2)
print(df1.append(df2,ignore_index=True))
A B
0 1 2
1 3 4
A B
0 5 6
1 7 8
A B
0 1 2
1 3 4
2 5 6
3 7 8
一行一行的给dataframe添加数据
dff = pd.concat(
[pd.DataFrame([i],columns=['A']) for i in range(5)],
ignore_index=True
)
print(dff)
A
0 0
1 1
2 2
3 3
4 4
work_dir = "./c15_excel_split_merge"
splits_dir = f"{work_dir}/splits"
import os
if not os.path.exists(splits_dir):
os.mkdir(splits_dir)
import pandas as pd
df_source = pd.read_excel("./c15_excel_split_merge/crazyant_blog_articles_source.xlsx")
print(df_source.head())
print(df_source.index)
#返回行、列
print(df_source.shape)
total_row = df_source.shape[0]
print(total_row)
id title tags
0 2585 Tensorflow怎样接收变长列表特征 python,tensorflow,特征工程
1 2583 Pandas实现数据的合并concat pandas,python,数据分析
2 2574 Pandas的Index索引有什么用途? pandas,python,数据分析
3 2564 机器学习常用数据集大全 python,机器学习
4 2561 一个数据科学家的修炼路径 数据分析
RangeIndex(start=0, stop=258, step=1)
(258, 3)
258
#将大Excel拆分给这几个人
user_names = ["xiao_shuai","xiao_wang","xiao_ming","xiao_lei","xiao_bo","xiao_hong"]
#计算每个人的任务数
#“//”运算符,取整除,返回商的整数部分(向下取整)
split_size = total_row // len(user_names)
if total_row % len(user_names):
split_size += 1
df_subs = []
for idx,user_name in enumerate(user_names):
#iloc开始、结束索引
begin = idx*split_size
end = begin+split_size
#df按照iloc拆分
df_sub = df_source.iloc[begin:end]
#df_subs存入一个元组
df_subs.append((idx,user_name,df_sub))
#将子dataframe存入Excel
for idx,user_name,df_sub in df_subs:
file_name = f"{splits_dir}/task_{idx}_{user_name}.xlsx"
df_sub.to_excel(file_name,index=False)
#列出Excel名称列表
excel_names = []
for excel_name in os.listdir(splits_dir):
excel_names.append(excel_name)
print(excel_names)
#读取到dataframe
df_list = []
for excel_name in excel_names:
excel_path = f"{splits_dir}/{excel_name}"
df_split = pd.read_excel(excel_path)
#解析username
user_name = excel_name.replace("task_","").replace(".xlsx","")[2:]
#给每个df加一列用户名称
df_split["username"] = user_name
df_list.append(df_split)
#df.concat合并
df_merge = pd.concat(df_list)
print(df_merge.shape)
print(df_merge.head())
df_merge.to_excel(f"{work_dir}/task_merge.xlsx",index=False)
(258, 4)
id title tags username
0 2585 Tensorflow怎样接收变长列表特征 python,tensorflow,特征工程 xiao_shuai
1 2583 Pandas实现数据的合并concat pandas,python,数据分析 xiao_shuai
2 2574 Pandas的Index索引有什么用途? pandas,python,数据分析 xiao_shuai
3 2564 机器学习常用数据集大全 python,机器学习 xiao_shuai
4 2561 一个数据科学家的修炼路径 数据分析 xiao_shuai
import pandas as pd
import numpy as np
#加上这行,能在jupyter notebook展示matplot图表
%matplotlib inline
#使用方式 data.plot()
df = pd.DataFrame({
'A':['foo','bar','foo','bar','foo','bar','foo','foo'],
'B':['one','one','two','three','two','two','one','three'],
'C':np.random.randn(8),
'D':np.random.randn(8)
})
print(df)
df1 = df.groupby('A').sum()
print(df1)
groupby的A列变成了数据的索引列;sum统计数字,B是字符所以被忽略。
A B C D
0 foo one -1.106856 0.713179
1 bar one 1.273161 0.342217
2 foo two -0.378437 3.338582
3 bar three -0.634966 -0.153653
4 foo two 0.044327 -0.189306
5 bar two 0.543985 -0.174611
6 foo one 0.352282 1.066336
7 foo three 1.231313 1.395095
C D
A
bar 1.182180 0.013953
foo 0.142628 6.323886
df1 = df.groupby(['A','B']).mean()
print(df1)
变成A B二级索引
C D
A B
bar one -0.520902 1.026888
three 0.607355 0.119211
two -1.670414 -0.730202
foo one -0.038131 1.442606
three -0.925947 -0.901537
two -0.611745 -0.216459
df1 = df.groupby(['A','B'],as_index=False).mean()
print(df1)
A B C D
0 bar one -1.801801 -0.353210
1 bar three -0.626959 1.805818
2 bar two -0.420621 1.374015
3 foo one 0.020856 0.557639
4 foo three -0.500431 -0.774059
5 foo two -0.541895 -0.177716
df1 = df.groupby('A').agg([np.sum,np.mean,np.std])
print(df1)
列变成了多级索引
C D
sum mean std sum mean std
A
bar 1.257328 0.419109 1.255378 -2.147189 -0.715730 0.901087
foo -2.009106 -0.401821 0.372771 1.737854 0.347571 0.638935
df1 = df.groupby('A')['C'].agg([np.sum,np.mean,np.std])
print(df1)
sum mean std
A
bar -0.494485 -0.164828 0.830111
foo -0.787843 -0.157569 0.728112
df1 = df.groupby('A').agg({"C":np.sum,"D":np.mean})
print(df1)
C D
A
bar 1.717162 -0.530213
foo 0.463014 -0.295544
g = df.groupby('A')
for name,group in g:
print(name)
print(group)
print()
bar
A B C D
1 bar one 1.691832 0.537865
3 bar three -0.581042 0.760365
5 bar two 1.162899 1.119155
foo
A B C D
0 foo one 0.211515 -0.009519
2 foo two 0.028462 1.434644
4 foo two -3.367568 1.996146
6 foo one -0.950889 0.573215
7 foo three 0.693937 0.408178
print(g.get_group('bar'))
A B C D
1 bar one -1.051277 -0.996631
3 bar three -1.298129 -2.053288
5 bar two -0.658050 1.274031
g = df.groupby(['A','B'])
for name,group in g:
print(name)
print(group)
print()
name是两个元素的tuple
('bar', 'one')
A B C D
1 bar one -1.13261 -1.871892
('bar', 'three')
A B C D
3 bar three 0.45064 0.443138
('bar', 'two')
A B C D
5 bar two 0.024066 -0.326454
('foo', 'one')
A B C D
0 foo one 1.241679 1.526465
6 foo one 1.535248 -1.096181
('foo', 'three')
A B C D
7 foo three 0.745874 -0.630024
('foo', 'two')
A B C D
2 foo two -0.033113 -0.058216
4 foo two -0.116838 1.180435
print(g.get_group(('foo','one')))
A B C D
0 foo one -1.294620 2.204648
6 foo one 2.306578 0.370950
直接查询group后的某几个列,生成Series或字Dataframe
print(g['C'])
for name,group in g['C']:
print(name)
print(group)
print(type(group))
print()
('bar', 'one')
1 0.147317
Name: C, dtype: float64
('bar', 'three')
3 -1.817367
Name: C, dtype: float64
('bar', 'two')
5 0.861903
Name: C, dtype: float64
('foo', 'one')
0 -0.097629
6 -1.862348
Name: C, dtype: float64
('foo', 'three')
7 0.365501
Name: C, dtype: float64
('foo', 'two')
2 1.713429
4 -1.001633
Name: C, dtype: float64
df = pd.read_csv('./beijing_tianqi_2018.csv')
df.loc[:,'bWendu'] = df['bWendu'].str.replace('℃','').astype('int32')
df.loc[:,'yWendu'] = df['yWendu'].str.replace('℃','').astype('int32')
print(df.head())
#新增一列月份
df['month'] = df['ymd'].str[:7]
print(df.head())
ymd bWendu yWendu tianqi fengxiang fengli aqi aqiInfo aqiLevel
0 2018-01-01 3 -6 晴~多云 东北风 1-2级 59 良 2
1 2018-01-02 2 -5 阴~多云 东北风 1-2级 49 优 1
2 2018-01-03 2 -5 多云 北风 1-2级 28 优 1
3 2018-01-04 0 -8 阴 东北风 1-2级 28 优 1
4 2018-01-05 3 -6 多云~晴 西北风 1-2级 50 优 1
ymd bWendu yWendu tianqi ... aqi aqiInfo aqiLevel month
0 2018-01-01 3 -6 晴~多云 ... 59 良 2 2018-01
1 2018-01-02 2 -5 阴~多云 ... 49 优 1 2018-01
2 2018-01-03 2 -5 多云 ... 28 优 1 2018-01
3 2018-01-04 0 -8 阴 ... 28 优 1 2018-01
4 2018-01-05 3 -6 多云~晴 ... 50 优 1 2018-01
[5 rows x 10 columns]
data = df.groupby('month')['bWendu'].max()
print(data)
month
2018-01 7
2018-02 12
2018-03 27
2018-04 30
2018-05 35
2018-06 38
2018-07 37
2018-08 36
2018-09 31
2018-10 25
2018-11 18
2018-12 10
Name: bWendu, dtype: int32
import numpy as np
group_data = df.groupby('month').agg({"bWendu":np.max,"yWendu":np.min,"aqi":np.mean})
print(group_data)
bWendu yWendu aqi
month
2018-01 7 -12 60.677419
2018-02 12 -10 78.857143
2018-03 27 -4 130.322581
2018-04 30 1 102.866667
2018-05 35 10 99.064516
2018-06 38 17 82.300000
2018-07 37 22 72.677419
2018-08 36 20 59.516129
2018-09 31 11 50.433333
2018-10 25 1 67.096774
2018-11 18 -4 105.100000
2018-12 10 -12 77.354839
import pandas as pd
stocks = pd.read_excel("./stocks/互联网公司股票.xlsx")
print(stocks.shape)
print(stocks.head(3))
#查看都有哪些公司
print(stocks['公司'].unique())
#查看收盘时平均值
print(stocks.groupby('公司')['收盘'].mean())
(12, 8)
日期 公司 收盘 开盘 高 低 交易量 涨跌幅
0 2019-10-03 BIDU 104.32 102.35 104.73 101.15 2.24 0.02
1 2019-10-02 BIDU 102.62 100.85 103.24 99.50 2.69 0.01
2 2019-10-01 BIDU 102.00 102.80 103.26 101.00 1.78 -0.01
['BIDU' 'BABA' 'IQ' 'JD']
公司
BABA 166.80
BIDU 102.98
IQ 15.90
JD 28.35
Name: 收盘, dtype: float64
ser = stocks.groupby(["公司","日期"])["收盘"].mean()
print(ser)
print(ser.index)
公司 日期
BABA 2019-10-01 165.15
2019-10-02 165.77
2019-10-03 169.48
BIDU 2019-10-01 102.00
2019-10-02 102.62
2019-10-03 104.32
IQ 2019-10-01 15.92
2019-10-02 15.72
2019-10-03 16.06
JD 2019-10-01 28.19
2019-10-02 28.06
2019-10-03 28.80
Name: 收盘, dtype: float64
MultiIndex([('BABA', '2019-10-01'),
('BABA', '2019-10-02'),
('BABA', '2019-10-03'),
('BIDU', '2019-10-01'),
('BIDU', '2019-10-02'),
('BIDU', '2019-10-03'),
( 'IQ', '2019-10-01'),
( 'IQ', '2019-10-02'),
( 'IQ', '2019-10-03'),
( 'JD', '2019-10-01'),
( 'JD', '2019-10-02'),
( 'JD', '2019-10-03')],
names=['公司', '日期'])
Process finished with exit code 0
#unstack把二级索引变成行
print(ser.unstack())
#把索引变成普通的列
print(ser.reset_index())
日期 2019-10-01 2019-10-02 2019-10-03
公司
BABA 165.15 165.77 169.48
BIDU 102.00 102.62 104.32
IQ 15.92 15.72 16.06
JD 28.19 28.06 28.80
公司 日期 收盘
0 BABA 2019-10-01 165.15
1 BABA 2019-10-02 165.77
2 BABA 2019-10-03 169.48
3 BIDU 2019-10-01 102.00
4 BIDU 2019-10-02 102.62
5 BIDU 2019-10-03 104.32
6 IQ 2019-10-01 15.92
7 IQ 2019-10-02 15.72
8 IQ 2019-10-03 16.06
9 JD 2019-10-01 28.19
10 JD 2019-10-02 28.06
11 JD 2019-10-03 28.80
print(ser.loc['BIDU'])
#使用元组定位到多重索引
print(ser.loc[('BIDU','2019-10-02')])
#逗号前第一个索引,逗号后是第二个索引
print(ser.loc[:,'2019-10-02'])
日期
2019-10-01 102.00
2019-10-02 102.62
2019-10-03 104.32
Name: 收盘, dtype: float64
102.62
公司
BABA 165.77
BIDU 102.62
IQ 15.72
JD 28.06
Name: 收盘, dtype: float64
#设置二级索引
stocks.set_index(['公司','日期'],inplace=True)
print(stocks.head())
print(stocks.index)
#索引排序
stocks.sort_index(inplace=True)
print(stocks)
收盘 开盘 高 低 交易量 涨跌幅
公司 日期
BIDU 2019-10-03 104.32 102.35 104.73 101.15 2.24 0.02
2019-10-02 102.62 100.85 103.24 99.50 2.69 0.01
2019-10-01 102.00 102.80 103.26 101.00 1.78 -0.01
BABA 2019-10-03 169.48 166.65 170.18 165.00 10.39 0.02
2019-10-02 165.77 162.82 166.88 161.90 11.60 0.00
MultiIndex([('BIDU', '2019-10-03'),
('BIDU', '2019-10-02'),
('BIDU', '2019-10-01'),
('BABA', '2019-10-03'),
('BABA', '2019-10-02'),
('BABA', '2019-10-01'),
( 'IQ', '2019-10-03'),
( 'IQ', '2019-10-02'),
( 'IQ', '2019-10-01'),
( 'JD', '2019-10-03'),
( 'JD', '2019-10-02'),
( 'JD', '2019-10-01')],
names=['公司', '日期'])
收盘 开盘 高 低 交易量 涨跌幅
公司 日期
BABA 2019-10-01 165.15 168.01 168.23 163.64 14.19 -0.01
2019-10-02 165.77 162.82 166.88 161.90 11.60 0.00
2019-10-03 169.48 166.65 170.18 165.00 10.39 0.02
BIDU 2019-10-01 102.00 102.80 103.26 101.00 1.78 -0.01
2019-10-02 102.62 100.85 103.24 99.50 2.69 0.01
2019-10-03 104.32 102.35 104.73 101.15 2.24 0.02
IQ 2019-10-01 15.92 16.14 16.22 15.50 11.65 -0.01
2019-10-02 15.72 15.85 15.87 15.12 8.10 -0.01
2019-10-03 16.06 15.71 16.38 15.32 10.08 0.02
JD 2019-10-01 28.19 28.22 28.57 27.97 10.64 0.00
2019-10-02 28.06 28.00 28.22 27.53 9.53 0.00
2019-10-03 28.80 28.11 28.97 27.82 8.77 0.03
在选择数据时
print(stocks.loc['BIDU'])
print(stocks.loc[('BIDU','2019-10-02'),:])
print(stocks.loc[('BIDU','2019-10-02'),'开盘'])
#BIDU和JD的03日所有信息dataframe
print(stocks.loc[(['BIDU','JD'],'2019-10-03'),:])
print(stocks.loc[(['BIDU','JD'],'2019-10-03'),'收盘'])
#BIDU两天的收盘价
print(stocks.loc[('BIDU',['2019-10-02','2019-10-03']),'收盘'])
结果:
收盘 开盘 高 低 交易量 涨跌幅
日期
2019-10-01 102.00 102.80 103.26 101.00 1.78 -0.01
2019-10-02 102.62 100.85 103.24 99.50 2.69 0.01
2019-10-03 104.32 102.35 104.73 101.15 2.24 0.02
收盘 102.62
开盘 100.85
高 103.24
低 99.50
交易量 2.69
涨跌幅 0.01
Name: (BIDU, 2019-10-02), dtype: float64
100.85
收盘 开盘 高 低 交易量 涨跌幅
公司 日期
BIDU 2019-10-03 104.32 102.35 104.73 101.15 2.24 0.02
JD 2019-10-03 28.80 28.11 28.97 27.82 8.77 0.03
公司 日期
BIDU 2019-10-03 104.32
JD 2019-10-03 28.80
Name: 收盘, dtype: float64
公司 日期
BIDU 2019-10-02 102.62
2019-10-03 104.32
Name: 收盘, dtype: float64
slice(None)代表筛选这一索引的所有内容
print(stocks.loc[(slice(None),['2019-10-02','2019-10-03']),:])
#把索引变成普通的列
print(stock.reset_index())
收盘 开盘 高 低 交易量 涨跌幅
公司 日期
BABA 2019-10-02 165.77 162.82 166.88 161.90 11.60 0.00
2019-10-03 169.48 166.65 170.18 165.00 10.39 0.02
BIDU 2019-10-02 102.62 100.85 103.24 99.50 2.69 0.01
2019-10-03 104.32 102.35 104.73 101.15 2.24 0.02
IQ 2019-10-02 15.72 15.85 15.87 15.12 8.10 -0.01
2019-10-03 16.06 15.71 16.38 15.32 10.08 0.02
JD 2019-10-02 28.06 28.00 28.22 27.53 9.53 0.00
2019-10-03 28.80 28.11 28.97 27.82 8.77 0.03
stocks = pd.read_excel("./stocks/互联网公司股票.xlsx")
print(stocks.head(3))
print(stocks['公司'].unique())
#小写公司拼音
dict_company_names = {
"bidu":"百度",
"baba":"阿里巴巴",
"iq":"爱奇艺",
"jd":"京东"
}
日期 公司 收盘 开盘 高 低 交易量 涨跌幅
0 2019-10-03 BIDU 104.32 102.35 104.73 101.15 2.24 0.02
1 2019-10-02 BIDU 102.62 100.85 103.24 99.50 2.69 0.01
2 2019-10-01 BIDU 102.00 102.80 103.26 101.00 1.78 -0.01
['BIDU' 'BABA' 'IQ' 'JD']
series.map(dict) or series.map(function)均可
df['gender'] = df['gender'].map({"mele":1,"female":2})
stocks['公司中文1'] = stocks["公司"].str.lower().map(dict_company_names)
print(stocks.head())
日期 公司 收盘 开盘 高 低 交易量 涨跌幅 公司中文1
0 2019-10-03 BIDU 104.32 102.35 104.73 101.15 2.24 0.02 百度
1 2019-10-02 BIDU 102.62 100.85 103.24 99.50 2.69 0.01 百度
2 2019-10-01 BIDU 102.00 102.80 103.26 101.00 1.78 -0.01 百度
3 2019-10-03 BABA 169.48 166.65 170.18 165.00 10.39 0.02 阿里巴巴
4 2019-10-02 BABA 165.77 162.82 166.88 161.90 11.60 0.00 阿里巴巴
stocks['公司中文2'] = stocks["公司"].map(lambda x:dict_company_names[x.lower()])
print(stocks.head())
日期 公司 收盘 开盘 高 低 交易量 涨跌幅 公司中文1 公司中文2
0 2019-10-03 BIDU 104.32 102.35 104.73 101.15 2.24 0.02 百度 百度
1 2019-10-02 BIDU 102.62 100.85 103.24 99.50 2.69 0.01 百度 百度
2 2019-10-01 BIDU 102.00 102.80 103.26 101.00 1.78 -0.01 百度 百度
3 2019-10-03 BABA 169.48 166.65 170.18 165.00 10.39 0.02 阿里巴巴 阿里巴巴
4 2019-10-02 BABA 165.77 162.82 166.88 161.90 11.60 0.00 阿里巴巴 阿里巴巴
#function的参数是每个Series里的值
stocks['公司中文3'] = stocks["公司"].apply(lambda x:dict_company_names[x.lower()])
#function的参数是对应轴的Series,axis=1,所以Series的key是列名,可以用x['公司']获取
stocks['公司中文4'] = stocks.apply(lambda x:dict_company_names[x['公司'].lower()],axis=1)
print(stocks.head())
日期 公司 收盘 开盘 高 ... 涨跌幅 公司中文1 公司中文2 公司中文3 公司中文4
0 2019-10-03 BIDU 104.32 102.35 104.73 ... 0.02 百度 百度 百度 百度
1 2019-10-02 BIDU 102.62 100.85 103.24 ... 0.01 百度 百度 百度 百度
2 2019-10-01 BIDU 102.00 102.80 103.26 ... -0.01 百度 百度 百度 百度
3 2019-10-03 BABA 169.48 166.65 170.18 ... 0.02 阿里巴巴 阿里巴巴 阿里巴巴 阿里巴巴
4 2019-10-02 BABA 165.77 162.82 166.88 ... 0.00 阿里巴巴 阿里巴巴 阿里巴巴 阿里巴巴
sub_df = stocks[['收盘','开盘','高','低','交易量']]
print(sub_df.head())
#将所有小数转换成整数,x是每个值
sub_df = sub_df.applymap(lambda x:int(x))
print(sub_df.head())
stocks.loc[:,['收盘','开盘','高','低','交易量']] = sub_df
print(stocks.head())
日期 公司 收盘 开盘 高 低 交易量 涨跌幅 公司中文1 公司中文2 公司中文3 公司中文4
0 2019-10-03 BIDU 104 102 104 101 2 0.02 百度 百度 百度 百度
1 2019-10-02 BIDU 102 100 103 99 2 0.01 百度 百度 百度 百度
2 2019-10-01 BIDU 102 102 103 101 1 -0.01 百度 百度 百度 百度
3 2019-10-03 BABA 169 166 170 165 10 0.02 阿里巴巴 阿里巴巴 阿里巴巴 阿里巴巴
4 2019-10-02 BABA 165 162 166 161 11 0.00 阿里巴巴 阿里巴巴 阿里巴巴 阿里巴巴
pandas的groupby遵从split、apply、combine模式
split指pandas的groupby,我们自己实现apply函数,apply返回的结果由pandas进行combine得到结果。
GroupBy.apply(function)
将不同范围的数值映射到[0,1]区间
公式:(x-xmin)/(xmax-xmin)
用户对电影评分的归一化
df_ratings = pd.read_csv(
"./movielens-1m/ratings.dat",
sep="::",
engine="python",
names="UserID::MovieID::Rating::Timestamp".split("::")
)
print(df_ratings.head())
def ratings_norm(df):
"""
df是每个用户分组的df
:param df:
:return:
"""
min_value = df["Rating"].min()
max_value = df["Rating"].max()
df["Rating_norm"] = df["Rating"].apply(lambda x:(x-min_value)/(max_value-min_value))
return df
df_ratings = df_ratings.groupby("UserID").apply(ratings_norm)
print(df_ratings.loc[df_ratings['UserID'] == 1,:].head())
#简写
#print(df_ratings[df_ratings['UserID'] == 1].head())
UserID MovieID Rating Timestamp
0 1 1193 5 978300760
1 1 661 3 978302109
2 1 914 3 978301968
3 1 3408 4 978300275
4 1 2355 5 978824291
UserID MovieID Rating Timestamp Rating_norm
0 1 1193 5 978300760 1.0
1 1 661 3 978302109 0.0
2 1 914 3 978301968 0.0
3 1 3408 4 978300275 0.5
4 1 2355 5 978824291 1.0
df = pd.read_csv('./beijing_tianqi_2018.csv')
df.loc[:,'bWendu'] = df['bWendu'].str.replace('℃','').astype('int32')
df.loc[:,'yWendu'] = df['yWendu'].str.replace('℃','').astype('int32')
#新增月份
df['month'] = df['ymd'].str[:7]
print(df.head())
ymd bWendu yWendu tianqi ... aqi aqiInfo aqiLevel month
0 2018-01-01 3 -6 晴~多云 ... 59 良 2 2018-01
1 2018-01-02 2 -5 阴~多云 ... 49 优 1 2018-01
2 2018-01-03 2 -5 多云 ... 28 优 1 2018-01
3 2018-01-04 0 -8 阴 ... 28 优 1 2018-01
4 2018-01-05 3 -6 多云~晴 ... 50 优 1 2018-01
[5 rows x 10 columns]
按month分组,取温度最高的几天
#按month分组,取温度最高的几天
def getWenduTopN(df,topn):
"""
df是按月份分组后的df
:return:
"""
#用bWendu排序,只取两列,然后切片语法取topn行
return df.sort_values(by="bWendu")[["ymd","bWendu"]][-topn:]
#apply中使用kv形式传入其他参数,比如topn
df1 = df.groupby('month').apply(getWenduTopN,topn=2)
print(df1.head())
ymd bWendu
month
2018-01 13 2018-01-14 6
18 2018-01-19 7
2018-02 53 2018-02-23 10
56 2018-02-26 12
2018-03 86 2018-03-28 25
将二维数据变成二维交叉形式,便于分析,叫做重塑或透视
统计得到电影评分数据集,每个月份每个分数被评分多少次:月份、分数1-5、次数
import numpy as np
df = pd.read_csv(
"./movielens-1m/ratings.dat",
sep="::",
engine="python",
names="UserID::MovieID::Rating::Timestamp".split("::"),
header=None
)
#转成时间格式可以使用pandas时间戳本身对象的方法
df["pdate"] = pd.to_datetime(df["Timestamp"],unit='s')
print(df.head())
print(df.dtypes)
#两列groupby,第一列是日期格式前的月份部分,第二列评分
df_group = df.groupby([df['pdate'].dt.month,'Rating'])['UserID'].agg(pv=np.sum)
print(df_group.head(10))
UserID MovieID Rating Timestamp pdate
0 1 1193 5 978300760 2000-12-31 22:12:40
1 1 661 3 978302109 2000-12-31 22:35:09
2 1 914 3 978301968 2000-12-31 22:32:48
3 1 3408 4 978300275 2000-12-31 22:04:35
4 1 2355 5 978824291 2001-01-06 23:38:11
UserID int64
MovieID int64
Rating int64
Timestamp int64
pdate datetime64[ns]
dtype: object
pv
pdate Rating
1 1 2613452
2 5294359
3 12273331
4 16452340
5 9580889
2 1 1608795
2 3747792
3 8608216
4 10941690
5 5819374
#将rating和pdate两个索引转成行+列的索引方式的二维数据
df_stack = df_group.unstack()
print(df_stack)
#使用jupyter notebook引用 %matplotlib inline 后可以展示图表
df_stack.plot()
#和unstack是互逆操作
print(df_stack.stack().head(10))
pv
Rating 1 2 3 4 5
pdate
1 2613452 5294359 12273331 16452340 9580889
2 1608795 3747792 8608216 10941690 5819374
3 1344378 2772172 6156512 6911661 3228406
4 4397883 10147641 25330546 30406281 18070625
5 24893943 41021601 99671422 138699142 98385825
6 15896973 31940801 75297592 109067096 72816021
7 22506252 44079974 118016191 163188814 104777329
8 42290096 80215303 196812819 250299153 165391463
9 10185866 19751997 49514561 66638484 43733790
10 6825621 14936083 37937741 49413212 31949765
11 29762500 55254306 133879416 181288004 118358977
12 5474475 11043533 25870578 33351106 19000303
AxesSubplot(0.125,0.11;0.775x0.77)
pv
pdate Rating
1 1 2613452
2 5294359
3 12273331
4 16452340
5 9580889
2 1 1608795
2 3747792
3 8608216
4 10941690
5 5819374
pivot方法相当于对df使用set_index创建分层索引,然后调用unstack
df_reset = df_group.reset_index()
print(df_reset.head())
#参数就是 y轴(pdate) x轴(Rating) 和值(pv)
df_pivot = df_reset.pivot('pdate','Rating','pv')
print(df_pivot.head())
df_pivot.plot()
pdate Rating pv
0 1 1 2613452
1 1 2 5294359
2 1 3 12273331
3 1 4 16452340
4 1 5 9580889
Rating 1 2 3 4 5
pdate
1 2613452 5294359 12273331 16452340 9580889
2 1608795 3747792 8608216 10941690 5819374
3 1344378 2772172 6156512 6911661 3228406
4 4397883 10147641 25330546 30406281 18070625
5 24893943 41021601 99671422 138699142 98385825
level=-1代表多层索引的最内层,可以通过==0/1/2指定多层索引的对应层
pandas可以将各种格式的日期数据转为pandas的日期对象,使用对象函数处理
# 小时
df["time"].dt.hour
# 月份
df["time"],dt.month
df = pd.read_csv('./beijing_tianqi_2018.csv')
df.loc[:,'bWendu'] = df['bWendu'].str.replace('℃','').astype('int32')
df.loc[:,'yWendu'] = df['yWendu'].str.replace('℃','').astype('int32')
df.set_index(pd.to_datetime(df["ymd"]),inplace=True)
print(df.head())
print(df.index)
datetime64[ns]格式就是pandas的Timestamp对象
ymd bWendu yWendu tianqi ... aqi aqiInfo aqiLevel month
ymd ...
2018-01-01 2018-01-01 3 -6 晴~多云 ... 59 良 2 2018-01
2018-01-02 2018-01-02 2 -5 阴~多云 ... 49 优 1 2018-01
2018-01-03 2018-01-03 2 -5 多云 ... 28 优 1 2018-01
2018-01-04 2018-01-04 0 -8 阴 ... 28 优 1 2018-01
2018-01-05 2018-01-05 3 -6 多云~晴 ... 50 优 1 2018-01
[5 rows x 10 columns]
DatetimeIndex(['2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04',
'2018-01-05', '2018-01-06', '2018-01-07', '2018-01-08',
'2018-01-09', '2018-01-10',
...
'2018-12-22', '2018-12-23', '2018-12-24', '2018-12-25',
'2018-12-26', '2018-12-27', '2018-12-28', '2018-12-29',
'2018-12-30', '2018-12-31'],
dtype='datetime64[ns]', name='ymd', length=365, freq=None)
#筛选固定的某一天
print(df.loc['2018-01-05'])
#日期区间
print(df.loc['2018-01-05':'2018-01-10'])
#按月份筛选
print(df.loc['2018-03'].head())
#按月份前缀筛选
print(df.loc['2018-07':'2018-09'].head())
#按年份前缀筛选
print(df.loc['2018'].head())
ymd 2018-01-05
bWendu 3
yWendu -6
tianqi 多云~晴
fengxiang 西北风
fengli 1-2级
aqi 50
aqiInfo 优
aqiLevel 1
month 2018-01
Name: 2018-01-05 00:00:00, dtype: object
ymd bWendu yWendu tianqi ... aqi aqiInfo aqiLevel month
ymd ...
2018-01-05 2018-01-05 3 -6 多云~晴 ... 50 优 1 2018-01
2018-01-06 2018-01-06 2 -5 多云~阴 ... 32 优 1 2018-01
2018-01-07 2018-01-07 2 -4 阴~多云 ... 59 良 2 2018-01
2018-01-08 2018-01-08 2 -6 晴 ... 50 优 1 2018-01
2018-01-09 2018-01-09 1 -8 晴 ... 34 优 1 2018-01
2018-01-10 2018-01-10 -2 -10 晴 ... 26 优 1 2018-01
[6 rows x 10 columns]
ymd bWendu yWendu tianqi ... aqi aqiInfo aqiLevel month
ymd ...
2018-03-01 2018-03-01 8 -3 多云 ... 46 优 1 2018-03
2018-03-02 2018-03-02 9 -1 晴~多云 ... 95 良 2 2018-03
2018-03-03 2018-03-03 13 3 多云~阴 ... 214 重度污染 5 2018-03
2018-03-04 2018-03-04 7 -2 阴~多云 ... 144 轻度污染 3 2018-03
2018-03-05 2018-03-05 8 -3 晴 ... 94 良 2 2018-03
[5 rows x 10 columns]
ymd bWendu yWendu tianqi ... aqi aqiInfo aqiLevel month
ymd ...
2018-07-01 2018-07-01 35 23 晴 ... 68 良 2 2018-07
2018-07-02 2018-07-02 32 23 多云~雷阵雨 ... 66 良 2 2018-07
2018-07-03 2018-07-03 32 24 雷阵雨~多云 ... 76 良 2 2018-07
2018-07-04 2018-07-04 35 26 多云 ... 96 良 2 2018-07
2018-07-05 2018-07-05 37 24 多云~雷阵雨 ... 104 轻度污染 3 2018-07
[5 rows x 10 columns]
ymd bWendu yWendu tianqi ... aqi aqiInfo aqiLevel month
ymd ...
2018-01-01 2018-01-01 3 -6 晴~多云 ... 59 良 2 2018-01
2018-01-02 2018-01-02 2 -5 阴~多云 ... 49 优 1 2018-01
2018-01-03 2018-01-03 2 -5 多云 ... 28 优 1 2018-01
2018-01-04 2018-01-04 0 -8 阴 ... 28 优 1 2018-01
2018-01-05 2018-01-05 3 -6 多云~晴 ... 50 优 1 2018-01
[5 rows x 10 columns]
#周数字列表
print(df.index.week)
#月数字列表
print(df.index.month)
#季度数字列表
print(df.index.quarter)
Int64Index([ 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
...
51, 51, 52, 52, 52, 52, 52, 52, 52, 1],
dtype='int64', name='ymd', length=365)
Int64Index([ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
...
12, 12, 12, 12, 12, 12, 12, 12, 12, 12],
dtype='int64', name='ymd', length=365)
Int64Index([1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
...
4, 4, 4, 4, 4, 4, 4, 4, 4, 4],
dtype='int64', name='ymd', length=365)
#统计每周最高温度
print(df.groupby(df.index.week)["bWendu"].max().head())
#jupyter中画图表
df.groupby(df.index.week)["bWendu"].max().plot()
#统计每月最高温度
print(df.groupby(df.index.month)["bWendu"].max())
#统计每季度最高温度
print(df.groupby(df.index.quarter)["bWendu"].max())
ymd
1 3
2 6
3 7
4 -1
5 4
Name: bWendu, dtype: int32
ymd
1 7
2 12
3 27
4 30
5 35
6 38
7 37
8 36
9 31
10 25
11 18
12 10
Name: bWendu, dtype: int32
ymd
1 27
2 38
3 37
4 25
Name: bWendu, dtype: int32
问题:按日期统计的数据,缺失了某天,导致数据不全该怎么补充日期
import pandas as pd
%matplotlib inline
df = pd.DataFrame({
"pdate":["2019-12-01","2019-12-02","2019-12-04","2019-12-05"],
"pv":[100,200,400,500],
"uv":[10,20,40,50]
})
df.set_index("pdate").plot()
缺失了12-03的数据,如何补充
#将索引变成日期格式
df_date = df.set_index("pdate")
df_date = df_date.set_index(pd.to_datetime(df_date.index))
print(df_date)
#连续的日期
pdates = pd.date_range(start="2019-12-01",end="2019-12-05")
print(pdates)
df_date_new = df_date.reindex(pdates,fill_value=0)
print(df_date_new)
df_date_new.plot()
pv uv
pdate
2019-12-01 100 10
2019-12-02 200 20
2019-12-04 400 40
2019-12-05 500 50
DatetimeIndex(['2019-12-01', '2019-12-02', '2019-12-03', '2019-12-04',
'2019-12-05'],
dtype='datetime64[ns]', freq='D')
pv uv
2019-12-01 100 10
2019-12-02 200 20
2019-12-03 0 0
2019-12-04 400 40
2019-12-05 500 50
resample的含义:改变数据的时间频率,比如把天数据变成月份,或者把小时数据变成分钟级别
resample语法:(DataFrame or Series).resample(arguments).(aggregate function)
#设置日期格式索引
df_new2 = df.set_index(pd.to_datetime(df["pdate"])).drop("pdate",axis=1)
print(df_new2)
#按天重采样,因为采样会让区间变成一个值,所以用mean平均值,每天只有一个数据所以平均值就是原值
df_new2 = df_new2.resample("D").mean().fillna(0)
print(df_new2)
#每两天的平均值
print(df_new2.resample("2D").mean())
pv uv
pdate
2019-12-01 100 10
2019-12-02 200 20
2019-12-04 400 40
2019-12-05 500 50
pv uv
pdate
2019-12-01 100.0 10.0
2019-12-02 200.0 20.0
2019-12-03 0.0 0.0
2019-12-04 400.0 40.0
2019-12-05 500.0 50.0
pv uv
pdate
2019-12-01 150.0 15.0
2019-12-03 200.0 20.0
2019-12-05 500.0 50.0
columns = ["col1", "col2"]
for col in columns:
df[col] = df[col].astype("category")
one-hot-encoding
index_col把第几列当初索引列
read_csv(“path”, index_col=0)
import pandas as pd
df_titanic = pd.read_csv("./titanic/titanic_train.csv")
print(df_titanic.head())
df_titanic.drop(columns=["Name","Ticket","Cabin"],inplace=True)
print(df_titanic.head())
print(df_titanic.info())
PassengerId Survived Pclass ... Fare Cabin Embarked
0 1 0 3 ... 7.2500 NaN S
1 2 1 1 ... 71.2833 C85 C
2 3 1 3 ... 7.9250 NaN S
3 4 1 1 ... 53.1000 C123 S
4 5 0 3 ... 8.0500 NaN S
[5 rows x 12 columns]
PassengerId Survived Pclass Sex Age SibSp Parch Fare Embarked
0 1 0 3 male 22.0 1 0 7.2500 S
1 2 1 1 female 38.0 1 0 71.2833 C
2 3 1 3 female 26.0 0 0 7.9250 S
3 4 1 1 female 35.0 1 0 53.1000 S
4 5 0 3 male 35.0 0 0 8.0500 S
RangeIndex: 891 entries, 0 to 890
Data columns (total 9 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 PassengerId 891 non-null int64
1 Survived 891 non-null int64
2 Pclass 891 non-null int64
3 Sex 891 non-null object
4 Age 714 non-null float64
5 SibSp 891 non-null int64
6 Parch 891 non-null int64
7 Fare 891 non-null float64
8 Embarked 889 non-null object
dtypes: float64(2), int64(5), object(2)
memory usage: 62.8+ KB
None
df_titanic["Age"] = df_titanic["Age"].fillna(df_titanic["Age"].mean())
print(df_titanic.info())
RangeIndex: 891 entries, 0 to 890
Data columns (total 9 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 PassengerId 891 non-null int64
1 Survived 891 non-null int64
2 Pclass 891 non-null int64
3 Sex 891 non-null object
4 Age 891 non-null float64
5 SibSp 891 non-null int64
6 Parch 891 non-null int64
7 Fare 891 non-null float64
8 Embarked 889 non-null object
dtypes: float64(2), int64(5), object(2)
memory usage: 62.8+ KB
None
print(pd.get_dummies(df_titanic["Sex"]).head())
female male
0 0 1
1 1 0
2 1 0
3 1 0
4 0 1
df转换
#df多列转换
needcode_cat_columns = ["Pclass","Sex","SibSp","Parch","Embarked"]
df_coded = pd.get_dummies(
df_titanic,
#要转码的列
columns=needcode_cat_columns,
#生成的列名的前缀
prefix=needcode_cat_columns,
#把空值也做编码
dummy_na=True,
#把1 of k移除(dummy variable trap)
drop_first=True
)
print(df_coded.head())
PassengerId Survived Age ... Embarked_Q Embarked_S Embarked_nan
0 1 0 22.0 ... 0 1 0
1 2 1 38.0 ... 0 0 0
2 3 1 26.0 ... 0 1 0
3 4 1 35.0 ... 0 1 0
4 5 0 35.0 ... 0 1 0
[5 rows x 26 columns]
y = df_coded.pop("Survived")
print(y.head())
X = df_coded
#X中没有Survived这一列了
print(X.head())
from sklearn.linear_model import LogisticRegression
#创建模型对象
logreg = LogisticRegression(solver='liblinear')
#实现模型训练
logreg.fit(X,y)
#准确率
print(logreg.score(X,y))
0 0
1 1
2 1
3 1
4 0
Name: Survived, dtype: int64
PassengerId Age Fare ... Embarked_Q Embarked_S Embarked_nan
0 1 22.0 7.2500 ... 0 1 0
1 2 38.0 71.2833 ... 0 0 0
2 3 26.0 7.9250 ... 0 1 0
3 4 35.0 53.1000 ... 0 1 0
4 5 35.0 8.0500 ... 0 1 0
[5 rows x 25 columns]
0.813692480359147
单指标统计:每个MovieID平均分
df.groupby("MovieID")["Rating"].mean()
单列多指标统计:每个MovieID的最高、最低、平均分
# =前是新df的列名,后面是函数名或者np中的函数
# agg(新列名=函数)
df.groupby("MovieID")["Rating"].agg(mean="mean",max="max",min=np.min)
df.groupby("MovieID").agg({"Rating":['mean','max',np.min]})
多个列多个指标统计:每个MovieID的评分人数,最高评分、最低、平均分
df_new = df.groupby("MovieID").agg(rating_mean=("Rating","mean"),user_count=("UserID",lambda x:x.nunique()))
out
rating_mean user_count
MovieID
1 4.146846 2077
2 3.201141 701
3 3.016736 478
4 2.729412 170
5 3.006757 296
... ... ...
df_new = df.groupby("MovieID").agg({"Rating":['mean','min','max'],"UserID":lambda x:x.nunique()})
print(df_new)
Rating UserID
mean min max
MovieID
1 4.146846 1 5 2077
2 3.201141 1 5 701
3 3.016736 1 5 478
4 2.729412 1 5 170
5 3.006757 1 5 296
... ... .. .. ...
将二级索引变成一级索引
#将2级索引变成1级索引
df_new.columns = ['ra_mean','ra_min','ra_max','user_cou']
print(df_new)
ra_mean ra_min ra_max user_cou
MovieID
1 4.146846 1 5 2077
2 3.201141 1 5 701
3 3.016736 1 5 478
4 2.729412 1 5 170
5 3.006757 1 5 296
... ... ... ... ...
df_new = df.groupby("MovieID").apply(lambda x:pd.Series({"min":x["Rating"].min(),"mean":x["Rating"].mean()}))
print(df_new)
min mean
MovieID
1 1.0 4.146846
2 1.0 3.201141
3 1.0 3.016736
4 1.0 2.729412
5 1.0 3.006757
... ... ...
import pandas as pd
df_grade = pd.read_excel("./c23_excel_vlookup/学生成绩表.xlsx")
df_sinfo = pd.read_excel("./c23_excel_vlookup/学生信息表.xlsx")
print(df_grade.head())
#两个表关联
#筛选几行
df_sinfo = df_sinfo[["学号","姓名","性别"]]
print(df_sinfo.head())
df_merge = pd.merge(left=df_grade,right=df_sinfo,left_on="学号",right_on="学号")
print(df_merge.head())
班级 学号 语文成绩 数学成绩 英语成绩
0 C01 S001 99 84 88
1 C01 S002 66 95 77
2 C01 S003 68 68 61
3 C01 S004 63 66 82
4 C01 S005 72 95 94
学号 姓名 性别
0 S001 怠涵 女
1 S002 婉清 女
2 S003 溪榕 女
3 S004 漠涓 女
4 S005 祈博 女
班级 学号 语文成绩 数学成绩 英语成绩 姓名 性别
0 C01 S001 99 84 88 怠涵 女
1 C01 S002 66 95 77 婉清 女
2 C01 S003 68 68 61 溪榕 女
3 C01 S004 63 66 82 漠涓 女
4 C01 S005 72 95 94 祈博 女
将姓名、性别调整到学号后
#转成python list
new_columns = df_merge.columns.to_list()
#[::-1]逆向先取性别再取姓名,insert的时候会再颠倒一次保证姓名、性别顺序
for name in ["姓名","性别"][::-1]:
new_columns.remove(name)
new_columns.insert(new_columns.index("学号")+1, name)
print(new_columns)
#使用new_columns重新索引
df_merge = df_merge.reindex(columns=new_columns)
print(df_merge.head())
#输出Excel
df_merge.to_excel("./c23_excel_vlookup/合并后的数据表.xlsx", index=False)
['班级', '学号', '姓名', '性别', '语文成绩', '数学成绩', '英语成绩']
班级 学号 姓名 性别 语文成绩 数学成绩 英语成绩
0 C01 S001 怠涵 女 99 84 88
1 C01 S002 婉清 女 66 95 77
2 C01 S003 溪榕 女 68 68 61
3 C01 S004 漠涓 女 63 66 82
4 C01 S005 祈博 女 72 95 94
echarts是百度开源的可视化图表库,pyechart是python库版本
import pandas as pd
df = pd.read_excel(r"C:\Users\Administrator\Desktop\jupyter_data\ant-learn-pandas\datas\stocks\baidu_stocks.xlsx", index_col="datetime", parse_dates=True)
df.sort_index(inplace=True)
df.head()
out
code open close high low vol p_change
datetime
2019-01-02 BIDU 156.179993 162.250000 164.330002 155.490005 2996952 NaN
2019-01-03 BIDU 158.750000 154.710007 159.880005 153.779999 3879180 -4.65
2019-01-04 BIDU 157.600006 160.949997 162.429993 157.250000 3847497 4.03
2019-01-07 BIDU 162.600006 162.600006 164.490005 158.509995 3266091 1.03
2019-01-08 BIDU 162.190002 163.399994 163.889999 158.160004 3253361 0.49
#使用pyecharts绘制折线图 pip install pyecharts
from pyecharts.charts import Line
from pyecharts import options as opts
#折线图
line = Line()
#x轴
line.add_xaxis(df.index.to_list())
#每个y轴
line.add_yaxis("开盘价", df["open"].round(2).to_list())
line.add_yaxis("收盘价", df["close"].round(2).to_list())
#图表配置
#TitleOpts设置标题
#TooltipOpts设置动态展示十字标
line.set_global_opts(
title_opts = opts.TitleOpts(title="百度股票2019"),
tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross")
)
#渲染数据,画图
line.render_notebook()
out
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wF5o9bso-1680050072813)(http://image.suifengxing.cn/note/python/pyecharts%E6%8A%98%E7%BA%BF%E5%9B%BE.PNG)]
pandas.Dataframe.explode(column),将dataframe的一个list-like的元素按行复制,index索引随之复制
import pandas as pd
df = pd.read_csv(r"C:\Users\Administrator\Desktop\jupyter_data\ant-learn-pandas\datas\movielens-1m\movies.dat",
header=None,
names="MovieID::Title::Generes".split("::"),
sep="::",
engine="python"
)
# print(df.head())
#将Genenres字段拆出list类型字段
df["Genere"] = df["Generes"].map(lambda x:x.split("|"))
# print(df.head())
df_new = df.explode("Genere")
print(df_new.head(10))
%matplotlib inline
df_new["Genere"].value_counts().plot.bar()
MovieID Title Generes Genere
0 1 Toy Story (1995) Animation|Children's|Comedy Animation
0 1 Toy Story (1995) Animation|Children's|Comedy Children's
0 1 Toy Story (1995) Animation|Children's|Comedy Comedy
1 2 Jumanji (1995) Adventure|Children's|Fantasy Adventure
1 2 Jumanji (1995) Adventure|Children's|Fantasy Children's
1 2 Jumanji (1995) Adventure|Children's|Fantasy Fantasy
2 3 Grumpier Old Men (1995) Comedy|Romance Comedy
2 3 Grumpier Old Men (1995) Comedy|Romance Romance
3 4 Waiting to Exhale (1995) Comedy|Drama Comedy
3 4 Waiting to Exhale (1995) Comedy|Drama Drama
Chrome插件可以复制cookie为json格式:https://www.editthiscookie.com/
JSON格式cookies复制到cookie.txt中
import requests.cookies
cookie_jar = requests.cookies.RequestsCookieJar()
with open("./cookie.txt") as fin:
cookieJson = json.loads(fin.read())
for cookie in cookieJson:
cookie_jar.set(
name=cookie["name"],
value=cookiep["value"],
domain=cookie["domain"],
path=cookie["path"]
)
htmls = []
url = "http://dict.youdao.com/wordbook/wordlist?p={idx}&tags="
for idx in range(6):
time.sleep(1)
print("爬取数据第%d页" % idx)
r = requests.get(url.format(idx=idx), cookies=cookie_jar)
htmls.append(r.text)
# 拼接多个html df
df_list = []
for html in htmls:
df = pd.read_html(html)
df_cont = df[1]
# 这里的df[0]是标头
df_cont.columns = df[0].columns
df_list.append(df_cont)
# 拼接多个html解析出的df
df_all = pd.concat(df_list)
import pandas as pd
file_path = r"./c39_explode_to_manyrows/读者提供的数据-输入.xlsx"
df = pd.read_excel(file_path)
print(df.head())
# 拿Supplier之后所有列名
merge_name = list(df.loc[:, "Supplier":].columns.values)
print(merge_name)
#把Supplier和Supplier PN合并成一个大字符串
def merge_column(x):
"""
x是一个series,把他们按分隔符合并
:param x:
:return:
"""
#删除为空的列
x = x[x.notna()]
# 使用x.values用于合并
y = x.values
# 合并后的列表,每个元素是Supplier Supplier PN 对
result = []
# range的步长为2,目的是每两列做合并
for idx in range(0, len(y), 2):
# 竖线是分隔符
result.append(f"{y[idx] }|{y[idx + 1]}")
# #分隔每个键值对
return "#".join(result)
#axis=1表示将每行作为series传入merge_column方法中
df["merge"] = df.loc[:,"Supplier":].apply(merge_column, axis=1)
print(df)
# 删除不需要的列 axis=1按列删除
df.drop(merge_name, axis=1, inplace=True)
print(df)
print(df.columns)
# 使用explode变成多行,先将merge列变为list形式才行
df["merge"] = df["merge"].str.split("#")
print(df)
df_explode = df.explode("merge")
print(df_explode)
# 将Supplier和Supplier PN对拆成两列
df_explode["Supplier"] = df_explode["merge"].str.split("|").str[0]
df_explode["Supplier PN"] = df_explode["merge"].str.split("|").str[1]
print(df_explode.columns)
print(df_explode)
df_explode.to_excel("./c39_explode_to_manyrows/读者提供的数据-输出.xlsx", index=False)
import pandas as pd
df = pd.read_csv("./tianqi/beijing_tianqi_2018.csv")
df["bWendu"] = df["bWendu"].str.replace("℃","").astype("int32")
df["yWendu"] = df["yWendu"].str.replace("℃","").astype("int32")
print(df.head())
df["ymd"] = pd.to_datetime(df["ymd"])
print(df.info())
# 可以用Series.unique去重
# 可以用",".join(series)实现数组合并成大字符串
print(",".join(df["fengxiang"].unique()))
result = (
df.groupby(df["ymd"].dt.month).agg(
# 新列名 = (原列名, 函数)
最高温度=("bWendu", "max"),
最低温度=("bWendu", "min"),
风向列表=("fengxiang", lambda x : ",".join(x.unique())),
空气质量列表=("aqiInfo", lambda x : ",".join(x.unique()))
)
.reset_index() # 把年月日索引变成了普通的列
.rename(columns={"ymd":"月份"}))
print(result)
月份 最高温度 最低温度 风向列表 空气质量列表
0 1 7 -4 东北风,北风,西北风,西南风,南风,东南风,东风 良,优,轻度污染,中度污染
1 2 12 -1 北风,西南风,南风,西北风,西风,东北风,东风 良,优,轻度污染,中度污染,重度污染
2 3 27 4 西南风,北风,东南风,南风,东北风,东风 优,良,重度污染,轻度污染,中度污染,严重污染
3 4 30 10 南风,北风,东北风,西南风,西北风,东南风 重度污染,良,优,轻度污染,中度污染
4 5 35 18 东北风,北风,西南风,南风,东南风,东风,西风,西北风 轻度污染,优,良,中度污染
5 6 38 23 西南风,南风,北风,东风,东南风,东北风 良,轻度污染,优,中度污染
6 7 37 25 东南风,西南风,南风,东北风,东风,西风,北风 良,轻度污染,优
7 8 36 26 东南风,南风,东风,东北风,北风,西南风 良,轻度污染,优
8 9 31 19 南风,北风,西南风,西北风 优,良,轻度污染
9 10 25 14 北风,西北风,南风,西风,东北风,西南风 优,良,轻度污染,中度污染
10 11 18 7 南风,北风,西南风,东南风,西北风,东北风 良,轻度污染,重度污染,优,中度污染
11 12 10 -5 东南风,东北风,西北风,西南风 中度污染,重度污染,良,优,轻度污染
import pandas as pd
df = pd.read_excel("./c42_split_onecolumn_tomany/学生数据表.xlsx")
print(df.head())
print(df.info())
def split_column(line):
line["姓名"], line["性别"], line["年龄"], line["籍贯"] = line["数据"].split(":")
return line
df = df.apply(split_column, axis=1)
print(df.head())
df = df.drop("数据", axis=1)
print(df.head())
for row in df.itertuples():
print(row)
print(row.Index, row.学号, row.姓名)
每个Excel和sheet格式相同
import pandas as pd
import os
dfs = []
# sheet_name=None读所有sheet
for fname in os.listdir("./concat/"):
if fname.endswith(".xls") and fname != "final.xls":
df = pd.read_excel(
fname,
header=None,
sheet_name=None
)
# df是 key=sheetName:value=df的字典。list.extend方法添加多项
dfs.extend(df.values())
result = pd.concat(dfs)
result.to_excel("./concat/final.xls", index=False)
import pandas as pd
df = pd.read_excel("./c23_excel_vlookup/学生信息表.xlsx")
print(df.head())
df2 = df.transpose()
print(df2.head())
学号 姓名 性别 年龄 籍贯
0 S001 怠涵 女 23 山东
1 S002 婉清 女 25 河南
2 S003 溪榕 女 23 湖北
3 S004 漠涓 女 19 陕西
4 S005 祈博 女 24 山东
0 1 2 3 4 5 ... 18 19 20 21 22 23
学号 S001 S002 S003 S004 S005 S006 ... S019 S020 S021 S022 S023 S024
姓名 怠涵 婉清 溪榕 漠涓 祈博 孝冉 ... 冬梅 箐莲 仪博 馨苒 云霖 海彤
性别 女 女 女 女 女 女 ... 女 女 女 男 男 男
年龄 23 25 23 19 24 22 ... 23 24 21 22 23 23
籍贯 山东 河南 湖北 陕西 山东 河南 ... 湖北 陕西 山东 河南 湖北 陕西
[5 rows x 24 columns]
columns = list(df.columns)
columns.remove("年龄")
columns.insert(columns.index("姓名"), "年龄")
print(columns)
df3 = df[columns]
print(df3.head())
['学号', '年龄', '姓名', '性别', '籍贯']
学号 年龄 姓名 性别 籍贯
0 S001 23 怠涵 女 山东
1 S002 25 婉清 女 河南
2 S003 23 溪榕 女 湖北
3 S004 19 漠涓 女 陕西
4 S005 24 祈博 女 山东
大数据量时,传给c语言实现,更快
Dataframe.query(expr,inplace=False,**kwargs)
expr为要返回boolean结果的字符串表达式,如:df.query('a<100') df.query('a < b & b < c')
import pandas as pd
df = pd.read_csv(r'tianqi/beijing_tianqi_2018.csv')
print(df.index)
df.set_index('ymd',inplace=True)
df.loc[:,'bWendu'] = df['bWendu'].str.replace('℃','').astype('int32')
df.loc[:,'yWendu'] = df['yWendu'].str.replace('℃','').astype('int32')
# 使用普通条件查询,必须有括号,不然有优先级问题
print(df[df["yWendu"] < -10].head())
df1 = df[(df["bWendu"]<=30)&(df["yWendu"]>=15)&(df["tianqi"]=="晴")]
print(df1.head())
#使用df.query简化查询
# Dataframe.query(expr,inplace=False,**kwargs)
print(df.query("yWendu < 3").head(3))
# 查温差大于15度的数据
print(df.query("bWendu - yWendu >= 15").head(3))
# 可使用外部变量 @符号
high_temp = 15
low_temp = 13
print(df.query("yWendu<=@high_temp & yWendu>=@low_temp").head(3))
df_new = df.query("yWenDu == 20").copy()
import pandas as pd
# list dict to series
list = ["数学","语文","英语"]
s = pd.Series(data=list)
# 索引是自动填充的数字
print(s)
dict = {"数学": 80, "语文": 90, "英语": 120}
s1 = pd.Series(data=dict)
# 索引是dict的key
print(s1)
# series to list/dict
numbers = s1.to_list()
print(numbers)
d = s1.to_dict()
print(d)
# series to dataframe
df = pd.DataFrame(data=s1, columns=["grade"])
print(df)
import numpy as np
# 借助numpy创建series
s = pd.Series(
np.arange(10, 100, 10),# 10-90,间隔10
index=np.arange(101, 110),# 索引:101-109,间隔1
dtype='float'# 类型float64
)
print(s)
# 字典创建dataframe
df = pd.DataFrame(
data={
"姓名": ["小张","小李"],
"年龄":[18,19]
}
)
print(df)
# 设置索引列
df.set_index("姓名", inplace=True)
print(df.index)
import pandas as pd
s = pd.Series(
data=["001","002","003","004"],
index=list("abcd")
)
# 数值转换成数字类型
s = s.apply(lambda x: int(x))
print(s)
# 或者astype
s = s.astype(int)
print(s)
# 存在的series数据添加元素
s = s.append(pd.Series(
data=[6,7],
index=['f','g']
))
print(s)
# series转换成dataframe
df = s.reset_index()
df.columns=["idx","cnt"]
print(df)
import pandas as pd
# 生成一个月的所有日期
date_range = pd.date_range(start='2021-10-01', end='2022-10-31')
# periods按天递增取31个数
date_range = pd.date_range(start='2021-10-01', periods=31)
print(date_range)
# 输出2021年10月所有周一的日期列表。freq是频率,W-MON表示周的第一天,freq可以参考官方文档
date_range = pd.date_range(start='2021-10-01', periods=31, freq='W-MON')
print(date_range)
# 生成2021-10-01当天所有小时时间
date_range = pd.date_range(start='2021-10-01', periods=24, freq='H')
print(date_range)
# 输出dataframe,包含2021-10月的31天,以及每天是在2021年的第几天
date_range = pd.date_range(start='2021-10-01', end='2022-10-31')
df = pd.DataFrame(data=date_range, columns=['day'])
# df['day']是日期格式,直接取.dt,dt上有日期操作属性。dayofyear这个日期在本年度的第几天
df['day_of_year'] = df['day'].dt.dayofyear
print(df)
# 生成日期和随机分布的dataframe
import numpy as np
date_range = pd.date_range(start='2021-01-01', periods=1000)
data = {
'norm' : np.random.normal(loc=0, scale=1, size=1000),# 正态分布1000个随机数
'uniform': np.random.uniform(low=0, high=1, size=1000),# 均匀分布1000个随机数
'binomial': np.random.binomial(n=1, p=0.2, size=1000)# 二项分布1000个随机数
}
df = pd.DataFrame(data=data, index=date_range)
print(df)
# 统计数据列的值出现次数 pd.Series.value_counts()
print(df['binomial'].value_counts())
import pandas as pd
df = pd.read_csv("./00700.HK.csv", index_col=0)
# 找出收盘价最低的一行
print(df["Close"].min())
print(df["Close"].min())
# argmin返回最小值所在索引;df.loc[[]]两个中括号返回个dataframe,一个[]返回series
print(df.loc[[df["Close"].argmin()]])
# 列重命名
# columns直接等于新列表覆盖原名称
df.columns = ["A","B"]
# rename,字典的方式,key原列,value新列名
df.rename(columns={"Date":"D","open":"o"},inplace=True)
import pandas as pd
import numpy as np
np.random.seed(66)
s1 = pd.Series(np.random.rand(20))
s2 = pd.Series(np.random.randn(20))
df = pd.concat([s1,s2], axis=1)
df.columns = ['col1', 'col2']
print(df)
# 截断现有数列,小于-1的为-1,大于1的为1
df['col3'] = df['col2'].clip(-1.0, 1.0)
print(df)
# 取最大的五个数
print(df['col1'].nlargest(5))
print(df['col1'].nsmallest(5))
# 累计加和值-每一行的值等于前面所有行的和
print(df.cumsum())
# 计算中位数-某一列从小到大排列取中间的数字 = 50%分位数
print(df['col2'].median())
print(df['col2'].quantile())
# dataframe变成字典
print(df.head(5).to_dict())
import pandas as pd
import numpy as np
np.random.seed(66)
# 随机10行4列dataframe
df = pd.DataFrame(np.random.rand(10, 4), columns=list('ABCD'))
# 使用loc筛选,类似df.query
print(df.loc[df['C'] > 0.8])
print(df.loc[(df['C'] > 0.3) & (df['D'] < 0.7)])
# for循环遍历dataframe。index索引,row数据
for index, row in df.head().iterrows():
print(row)
# 指定特定单元格的值:iloc设置数字索引值、loc设计行标签的值
# iloc 第一个参数是数字索引值;第二个参数是列数,1是第2行 B
df.iloc[3, 1] = np.nan
# loc 第一个参数是行标签,第9行;第二个参数是列名
df.loc[8, 'D'] = np.nan
print(df)
# 移除包含空值得行
df2 = df.dropna()
print(df2)
# 重置索引,让索引连续
df2 = df2.reset_index(drop=True)
print(df2)
# 统计每列空值个数。isnull返回true和false,sum时true=1 false=0
print(df.isnull().sum())
# 填充空值
df = df.fillna(0)
print(df)
# 修改列顺序
df = df[['D','A','B','C']]
print(df)
# 删除列
print(df.drop("D", axis=1))
print(df.drop(["C","D"], axis=1))
import pandas as pd
import numpy as np
df = pd.read_csv("")
# np.where用法值为null bhp时替换成真的空值,否则不变
df["power"] = np.where(df["power"] == "null bhp", np.nan, df["power"])
df.duplicated()筛选出重复行
# 和前面重复了返回true,否则false的series
print(df.duplicated())
# 找出那个行和前面重复
print(df[df.duplicated()])
# 删除重复行
df = df.drop_duplicates()
# 筛选类型为object的列
print(df.select_dtypes(include=["object"]))
# 行变列,列变行
print(df.describe().T)
# drop_first,比如转成了男女为两个字段,转为0 1,会去掉第一行,只用一个男=0/1标识即可
# get_dummies会将一列转为多列,数量为里面字符串去重后的个数
df_dummies = pd.get_dummies(df, drop_first=True)
print(df.info())
字符串数据列不会出现
# 返回的也是个dataframe
corr = df_dummies.corr()
print(corr[["charges"]].sort_values(by="charges",ascending=False))
data = df_dummies.copy()
target = data.pop("charges")
# target是charges这一列的series
pd.read_json();
json格式是dict like:
# 0 1 是索引数值
{
"col1":{
"0":"11",
"1":"22"
},
"col2":{
"0":"33",
"1":"44"
}
}
# 每个值出现的次数
df_counts = df["country"].value_counts()
# 出现次数大于1的,返回true和false的series
print(df_counts > 1)
# 只输出数量大于1的值
print(df_counts[df_counts > 1])
print(df.iloc[df['value'].argmax())
# 索引相同的列放到了同一行中
pd.concat([df1, df2], axis=1)
# 计算股票的变动百分比 (收盘/开盘 - 1)*100
df['bidu_change'] = (df['bidu_close'] / df['bidu_open' - 1) * 100
# 判断>0是布尔类型series数据,再*1变为数字 true->1 false->0
df['flag'] = (df['col1']*df['col2'] > 0) * 1
len(df)