Pandas

  • Post author:
  • Post category:其他


Pandas主要处理三个数据结构

  • Series (序列) 处理一维数据
  • DataFrame (数据帧) 处理二维数据
  • Panel (面板) 处理三维数据

显示所有列

pd.set_option(‘display.max_columns’, None)

len(df)表示行数

转化类型的时候要记得把变量重新给该字段

today_world['病死率'] = today_world['病死率'].astype('float')

获取series的值.values[0]



Series的创建

语法: pandas.Series( data, index, dtype, name, copy, fastpath)

Serie默认的index从0开始, 也可以自己指定



默认创建

s1 = pd.Series(
    [1, 2, 3, 4, 5, 6, 7],
    index=["周一", "周二", "周三", "周四", "周五", "周六", "周日"],
    )
print(s1)



用ndarray创建Series

n1 = np.arange(1,11)
s2 = pd.Series(n1)
print(s2)



用字典创建Series

d = {4: 'four', 5: 'five', 6: 'five', 7: 'seven'}
s4 = pd.Series(dz,index=[5,4,7,6,1])
# 若索引自定义的顺序不同, 则会变换,没有的索引值为nan
print(s4)



Series的索引,切片

d = {'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5, 'six': 6, 'seven': 7}
s4 = pd.Series(d)
# 按默认的索引顺序来查找
print(s4[3])
print(s4[:3])
# 按索引的值来查找
print(s4['one'])
print(s4[['one','two','six']])



得到Series的索引和值的列表

print(s4.index.tolist())
print(s4.values.tolist())



Series的排序统计

rate = pd.Series(
    data=[3,4,5,3,5,2,1,3,5,4,3,3,5],
    name='评分',
)
print(rate.value_counts())	# 统计系列中每个值出现的次数,以 值 次数 的形式返回,降序排列
print(rate.value_counts()[]) # 得到某个值出现的个数
print(rate.sort_values())	# 按Series的值进行升序排列
d = {4: 'four', 5: 'five', 1: 'one', 7: 'seven'}
# 按索引进行排序, 降序
print(pd.Series(d).sort_index(ascending=False))



DataFrame的创建

语法: pandas.DataFrame( data, index, columns, dtype, copy)

data: 可以是列表, 字典等, 若用字典创建,则value要使用列表形式

list1 = [['张三', 23, '男'], ['李四', 27, '女'], ['王二', 26, '女']]
df1 = pd.DataFrame(list1, columns=['姓名', '年龄', '性别'])
df2 = pd.DataFrame({'姓名': ['张三', '李四', '王二'],
                    '年龄': [23, 27, 26],
                    '性别': ['男', '女', '女']
                    })

arr3 = np.array(list1)
df3 = pd.DataFrame(arr3,columns=['姓名','年龄','性别'])
print(df1)
print(df2)
print(df3)



查看dataframe的属性(获取表头)

用法 解释
df.info() 查看df的信息
df.head/tail(number) 查看df的前/后几列
df.index df的索引(行标签)
df.values 返回DataFrame的Numpy表示形式
df.columns df的列标签。
df.ndim 返回一个表示轴数/数组维数的整数。
df.size 返回一个表示此对象中元素数量的int。
df.shape 返回一个表示df维数的元组。
df = df.astype({‘列名’:‘数据类型’}) 把df中的某几列的数据类型强制转换
df.describe(incloude) 描述数据的有些相关性信息, 参数=”all”表示非数值类型也进行描述



df的索引(数据查找,筛选)

用法 解释
df[‘列名’] 索引处所要的列的书v就
df.loc[行索引名/条件, 列名] 通过标签或布尔数组访问一组行和列。
df.iloc[] 通过索引数字来访问 [前几行或[1,2]第二行第三行 ,需要的列数或[1,3]第二列,第四列]
df[].isin() 判断某列的值是否存在于[]
df.set_index(‘列名’) 将某一列设置为索引
list1 = [['张三', 23, '男'], ['李四', 27, '女'], ['王二', 26, '女']]
arr3 = np.array(list1)
df3 = pd.DataFrame(arr3,columns=['姓名','年龄','性别'],index=[['第一个','第二个','第三个']])
print(df3)
'''
     姓名  年龄 性别
第一个  张三  23  男
第二个  李四  27  女
第三个  王二  26  女
'''
df3.loc[df3['性别'] == '男','性别'] = 1
df3.loc[df3['性别'] == '女','性别'] = 0
print(df3)
'''
     姓名  年龄 性别
第一个  张三  23  1
第二个  李四  27  0
第三个  王二  26  0
'''
print(df3.loc[['第一个','第三个'],'姓名'])
'''
第一个    张三
第三个    王二
'''
print('-'*11)
print(df3.iloc[[0,2],[0,-1]])
'''
     姓名 性别
第一个  张三  男
第三个  王二  女
'''
print(df3.iloc[0:3,2])
'''
第一个    男
第二个    女
第三个    女
'''
df3['性别'] = np.where(df3['性别']=='男','1','0')
print(df3)
df3.loc[df3['性别']=='男','性别']='1'
df3.loc[df3['性别']=='女','性别']='0'
print(df3)
'''
     姓名  年龄 性别
第一个  张三  23  1
第二个  李四  27  0
第三个  王二  26  0
     姓名  年龄 性别
第一个  张三  23  1
第二个  李四  27  0
第三个  王二  26  0
'''



df的运算统计



求表中某几列的和

print(df.iloc[:,1:8].sum(axis=1))
# 表中所有行, 1到7列的和, axis表示求列之和, 默认为求每行该列的值的和


运算统计

df3['年龄'] = df3['年龄'].astype(int)
df3['年龄'] = df3['年龄']*2
print(df3)



对数据进行增删改

语法 描述
df.drop(labels=[行/列索引名称], axis, inplace) 删除某行/列
df.insert(loc, column, value) 选择列的索引位, 列名, 数据插入
df.drop(df[df["用户年龄"]<q1-1.5*iqr].index,inplace=True)
df.drop(df[df["用户年龄"]<q2+3*iqr].index,inplace=True)
# 增加列
df3['是否成年'] = np.where(df3['年龄']>'18','是','否')
df3['国籍'] = ['中国','中国','中国']
print(df3)
'''
     姓名  年龄 性别 是否成年  国籍
第一个  张三  23  1    是  中国
第二个  李四  27  0    是  中国
第三个  王二  17  0    否  中国
'''
# 删除列
df3.drop(labels=['是否成年','国籍'],axis=1,inplace=True)
print(df3)
# 删除行
df3.drop(labels=['第一个','第三个'],axis=0,inplace=True)
print(df3)
# 插入
df3.insert(0,'国籍',['中国','中国','中国'])
print(df3)



对于缺失值的处理



删除

对于缺失值可以计算一下该字段缺失值的占比

volum = df.apply(lambda x: sum(x.isnull())/len(x), axis=0)

若缺失值过多可以剔除这一列

语法: df.dropna(how, subset=[], inplace) 默认为any只要有缺失值就删除

how:all->全为缺失值才删除

subset: 指定哪些列为空,才删除该行

df = pd.DataFrame({'姓名': ['张三', '李四', '王二','赵六','赵四','王五'],
                    '年龄': [23, 27, 26,23,None,None],
                    '性别': ['男', '女', '女',None,np.nan,'男']
                    })
print(df)
'''
   姓名    年龄    性别
0  张三  23.0     男
1  李四  27.0     女
2  王二  26.0     女
3  赵六  23.0  None
4  赵四   NaN   NaN
5  王五   NaN     男
'''
df.dropna(how='any',subset=['姓名','性别'],inplace=True)
print(df)
'''
   姓名    年龄 性别
0  张三  23.0  男
1  李四  27.0  女
2  王二  26.0  女
5  王五   NaN  男
'''



填补

对于缺失值可以用0填补,若为int型可以用其一整列的均值,众数来填充

若为str类型可以用其出现最多的值来填充

语法: df.fillna(value, method, inplace)

value: 指定填充的值, 可用字典形式每列所要填充的类型

method: ffill/bfill 向前/后填充

mode = df['性别'].mode()[0]
df.fillna(value={'年龄':df['年龄'].mean(),'性别':df['性别'].mode()[0]},inplace=True)
print(df)
'''
   姓名     年龄 性别
0  张三  23.00  男
1  李四  27.00  女
2  王二  26.00  女
3  赵六  23.00  女
4  赵四  24.75  女
5  王五  24.75  男
'''



对于重复值的处理

首先要查看是否存在重复值

print(any(df.duplicated()))
# 显示重复的行
print(df[df.duplicated()])

语法: df.drop_duplicates(subset, keep, inplace, ignore_index)

subset: 指定哪些字段重复才删除(类似于sql的unique)

keep: first: 从第二个开始, 和第一个相同的就为重复值, 返回True

last: 从倒数第二个开始, 和倒数第一个相同的就为重复值, 返回True

ignore_index: 删除重复之后, 重置索引

删除重复数据(所有字段的相同的才删除)

df.drop_duplicates(subset=['姓名','性别'],inplace=True,ignore_index=True)
print(df)
'''
   姓名    年龄    性别
0  张三  23.0     男
1  李四  27.0     女
2  王二  26.0     女
3  赵六  23.0  None
4  赵四   NaN   NaN
5  王五   NaN     男
6  王二  26.0     男
'''



分组聚合



分组

语法: df.groupby(by=[])

by: 可以是多个列名

使用groupby对象,可以遍历类似itertools.obj的对象。

ipl_data = {'Team': ['Riders', 'Riders', 'Devils', 'Devils', 'Kings',
         'kings', 'Kings', 'Kings', 'Riders', 'Royals', 'Royals', 'Riders'],
         'Rank': [1, 2, 2, 3, 3,4 ,1 ,1,2 , 4,1,2],
         'Year':[2014,2015,2014,2015,2014,2015,2016,2017,2016,2014,2015,2017],
         'Points':[876,789,863,673,741,812,756,788,694,701,804,690]}
df = pd.DataFrame(ipl_data)
print(df)
# print(df.set_index(['Year','Team']))
grouped = df.groupby('Year')
print(grouped)
for name,group in grouped:
    print (name)
    print (group)
'''
2014
     Team  Rank  Year  Points
0  Riders     1  2014     876
2  Devils     2  2014     863
4   Kings     3  2014     741
9  Royals     4  2014     701
2015
      Team  Rank  Year  Points
1   Riders     2  2015     789
3   Devils     3  2015     673
5    kings     4  2015     812
10  Royals     1  2015     804
2016
     Team  Rank  Year  Points
6   Kings     1  2016     756
8  Riders     2  2016     694
2017
      Team  Rank  Year  Points
7    Kings     1  2017     788
11  Riders     2  2017     690
'''


借鉴易百教程



聚合

对分组后的对象使用聚合函数(可以有多个聚合函数)

# 对队伍做分组, 依据队伍分数的总和,平均值做聚合
x = df.groupby(['Team']).agg([np.sum, np.mean])['Points']
# 若不指定对哪一列做聚合则默认对全部列
print(x)
'''
         sum        mean
Team                    
Devils  1536  768.000000
Kings   2285  761.666667
Riders  3049  762.250000
Royals  1505  752.500000
kings    812  812.000000
'''
# 也可以用字典的形式
x = df.groupby(['Team']).agg({'Points':[np.sum,np.mean],'Rank':[np.sum,np.mean]})
print(x)
'''
       Points             Rank          
          sum        mean  sum      mean
Team                                    
Devils   1536  768.000000    5  2.500000
Kings    2285  761.666667    5  1.666667
Riders   3049  762.250000    7  1.750000
Royals   1505  752.500000    5  2.500000
kings     812  812.000000    4  4.000000
'''



透视表

语法: df.pivot_table(data, value, index, columns aggfunc, fill_value,

margins, margins_name)

value: 要汇总的列(可选)

index: 行分组键

column: 列分组键

aggfunc: 使用的聚合函数(可用字典)

fill_value: 用于替换缺失值

margins: 是否需要总计

margins_name: 总计的名称

pivot = pd.pivot_table(
    data=df,
    values=["Points","Rank"],
    index="Team",
    aggfunc=[np.mean]
)
print(pivot)



数据的,连接

pd.concat([data1,data2], join=”, ignor_index=False)

df1= pd.DataFrame(np.ones([3,4],dtype=int),columns=['a','b','c','d'])
df2 = pd.DataFrame(np.zeros([3,4], dtype=int), columns=['b','c','d','e'])
print(df1)
print(df2)
   a  b  c  d
0  1  1  1  1
1  1  1  1  1
2  1  1  1  1

   b  c  d  e
0  0  0  0  0
1  0  0  0  0
2  0  0  0  0

con = pd.concat([df1,df2],join='inner',ignore_index=True)	# 留下相同的, 把不同的列去掉
print(con)
   b  c  d
0  1  1  1
1  1  1  1
2  1  1  1
3  0  0  0
4  0  0  0
5  0  0  0

语法:pd.merge(left, right, how=‘inner’, on=None, left_on=None, right_on=None)

left: 左边的数据集

right: 右边的数据集

how: 连接方式: inner outer left right

on: 选择连接的键

left_on: 左边连接的键

right_on: 右边连接的键

data1 = pd.DataFrame({
    'key':['a','b','a','c','b','d'],
    'data1':[1,2,3,4,5,6]
})
data2 = pd.DataFrame({
    'rkey':['a','b','c'],
    'data2':[8,9,7]
})
data3 = pd.DataFrame({
    'key':['a','b','a','c','b','d'],
    'data1':[1,2,3,4,5,6]
})
data4 = pd.DataFrame({
    'key':['a','b','c'],
    'data2':[8,9,7]
})
print(pd.merge(data3,data4,how='left',on='key'))
merge = pd.merge(data1,data2,left_on='key',right_on='rkey',how='left')
# 若两个表要合并的列名不同,需要指定left_on和right_on,how,再把不需要的列删除即可
merge.drop('rkey',axis=1,inplace=True)
print(merge)
'''
  key  data1  data2
0   a      1    8.0
1   b      2    9.0
2   a      3    8.0
3   c      4    7.0
4   b      5    9.0
5   d      6    NaN
  key  data1  data2
0   a      1    8.0
1   b      2    9.0
2   a      3    8.0
3   c      4    7.0
4   b      5    9.0
5   d      6    NaN
'''



数据的转换



日期格式的转换

用to_datetime()方法将文本格式转换为日期格式

dataframe数据类型如果为datetime4, 可以使用dt方法取出年月日等

对于时间差数据,可以使用timedelta函数将其转换为指定的时间单位的数值

时间差数据可以使用dt方法访问其常用属性

# 把数据变成时间格式再提取年份数据
# 方法1
ffp = data['FFP_DATE'].apply(lambda x:datetime.strptime(x, '%Y/%m/%d'))
ffp_year = ffp.map(lambda x: x.year)
print(ffp_year)
# 方法2
data["FFP_DATE"] = pd.to_datetime(data['FFP_DATE'],format='%Y/%m/%d',errors='coerce')
print(data["FFP_DATE"].dt.year)
print(df['day'].head(5))
'''
0    20140919
1    20131011
2    20131011
3    20141023
4    20141103

'''
# 把日期转换为相对应的格式errors coerce==格式不对的变为nat
df['buy_day'] = pd.to_datetime(df['day'],format='%Y%m%d',errors='coerce')
print(df['buy_day'].head(5))
'''
0   2014-09-19
1   2013-10-11
2   2013-10-11
3   2014-10-23
4   2014-11-03
'''



利用map,appl转换

df = pd.DataFrame({"id":[1,2,3,4,5,6], "grade":['A', 'B', 'B', 'A', 'C', 'D']})
print(df.info())
print('---')
print(df)
'''
   id grade
0   1     A
1   2     B
2   3     B
3   4     A
4   5     C
5   6     D
'''
def translate(x):
    if x=='A':
        return '优秀'
    if x =='B':
        return '良好'
    if x == 'C':
        return '及格'
    if x=='D':
        return '不及格'
# df['raw_grade'] = df['raw_grade'].apply(translate)
# print(df)
df['grade'] = df['grade'].map({'A':"优秀",'B':'良好','C':'及格','D':'不及格'})
print(df)
'''
   id grade
0   1    优秀
1   2    良好
2   3    良好
3   4    优秀
4   5    及格
5   6   不及格
'''



读取,保存,合并文件



CSV

语法: pd.read_csv(filepath_or_buffer, sep=’,’, names=None, index_col=None, dtypy=,encording=‘utf-8’ )

filepath_or_buffer: 文件路径

sep: 分隔符

name: 自定义表头

index_col: 自定义索引列

dtype: 可以用字典的形式指定某些列的数据结构



Excel

语法: pd.read_excel(io, sheet_name)

io: 文件路径

sheet_name: 指定工作簿



合并多个工作簿

import xlrd
wordbook = xlrd.open_workbook('meal_order_detail.xlsx')
sheet_name = wordbook.sheet_names()
# print(sheet_name)   # 以列表的形式显示出工作簿的名称
order1 = pd.read_excel('meal_order_detail.xlsx',sheet_name='meal_order_detail1')
order2 = pd.read_excel('meal_order_detail.xlsx',sheet_name='meal_order_detail2')
order3 = pd.read_excel('meal_order_detail.xlsx',sheet_name='meal_order_detail3')

# 工作簿合并, 并且重置索引,纵向堆叠
'''
# 方法一
order = pd.concat([order1,order2,order3],axis=0,ignore_index=True)
print(order.tail(10))
'''
'''
# 方法二
basic = pd.DataFrame()
for i in sheet_name:
    basic_i = pd.read_excel('meal_order_detail.xlsx',sheet_name=i)
    basic = pd.concat([basic,basic_i],axis=0,ignore_index=True)
print(basic.shape)
'''



SQL

对于sqlite数据库

conn = sqlite3.connect('***.db')
sql = "select * from table_name"
comment_data = pd.read_sql_query(sql, conn)

对于MySQL

from sqlalchemy import create_engine
def query(table):
    user = 'root'
    password = '***'
    ip = 'localhost'
    port = 3306
    database = '***'
    conn = create_engine(r'mysql+pymysql://{}:{}@{}:{}/{}'.format(user,password,ip,port,database))
    sql = "select * from {}".format(table)
    return pd.read_sql(sql,conn)



文件保存

df.to_excel('***.xlsx',encording='utf-8',index=False)
df.to_csv('*****.csv',encoding='utf-8',index=False)

# 把多个df保存存到同一个excel文件的不同sheet中
writer = pd.ExcelWriter("中国各省的数据.xlsx")	# 设置文件路径
df.to_excel(writer,encoding='utf-8',index=False,sheet_name=df_name[i]+"的数据")
writer.save()




# 将多个df放到同一个excel的同一个sheet中
import pandas as pd
df = pd.DataFrame({'姓名': ['张三', '李四', '王二'],
                    '年龄': [23, 27, 26],
                    '性别': ['男', '女', '女']
                    })

df2 = df.copy()
dfs = []

dfs.append(df)
dfs.append(df2)
df = pd.concat(dfs)
df.to_excel('test3.xlsx',index=False)



脱敏处理

import pandas as pd
df = pd.read_excel('sfz.xlsx',dtype=str)
print(df)
df['脱敏处理后'] = df['身份证号码'].apply(lambda x:str(x).replace(x[5:15],'**********'))
print(df)

'''
                身份证号码
0  110101199003076992
1  110101199003074000
2  110101199003076992
3  110101199003074000
4  110101199003072000
                身份证号码               脱敏处理后
0  110101199003076992  11010**********992
1  110101199003074000  11010**********000
2  110101199003076992  11010**********992
3  110101199003074000  11010**********000
4  110101199003072000  11010**********000
'''



循环读取数据, 保存到一个excel文件中

each_nations_day_list_df = pd.read_excel(r'E:\Python_Project\COVID-19疫情的数据科学实践\各国数据_2020-04-22.xlsx')
# each_nation_writer =pd.ExcelWriter('各国每日数据.xlsx')
data1 = pd.DataFrame()
for i in range(3):
    url = 'https://c.m.163.com/ug/api/wuhan/app/data/list-by-area-code?areaCode={}'.format(each_nations_day_list_df['id'].iloc[i])
    time.sleep(0.5)
    r = requests.get(url,headers=headers)
    data_json = json.loads(r.text)
    data = get_data(data_json['data']['list'],['date','lastUpdateTime'])
    data['name'] = each_nations_day_list_df['name'][i]
    data['id'] = each_nations_day_list_df['id'][i]
    all_data = pd.concat([data,data1])
    data1 = all_data
all_data.to_excel('测hi.xlsx')



循环读取数据, 保存到一个excel文件中


each_nations_day_list_df = pd.read_excel(r'E:\Python_Project\COVID-19疫情的数据科学实践\各国数据_2020-04-22.xlsx')
# each_nation_writer =pd.ExcelWriter('各国每日数据.xlsx')
data1 = pd.DataFrame()
for i in range(3):
    url = 'https://c.m.163.com/ug/api/wuhan/app/data/list-by-area-code?areaCode={}'.format(each_nations_day_list_df['id'].iloc[i])
    time.sleep(0.5)
    r = requests.get(url,headers=headers)
    data_json = json.loads(r.text)
    data = get_data(data_json['data']['list'],['date','lastUpdateTime'])
    data['name'] = each_nations_day_list_df['name'][i]
    data['id'] = each_nations_day_list_df['id'][i]
    data.to_csv('测试2csv.csv',mode='a',encoding='utf_8_sig')



提取数值类型的数据

df.select_dtypes(include=[np.number])



设置某列为索引,某列为数据pivot

import seaborn as sns
import pandas as pd
df2 = pd.DataFrame({'姓名': ['张三', '李四', '王二'],
                    '年龄': [23, 27, 26],
                    '性别': ['男', '女', '女'],
                    '工资': [100,200,300],
                    '省份': ['福建','浙江','广东']
                    })
print(df2)
print('--=--')
print(df2.pivot(index='姓名',columns='省份',values=['工资','性别']))
‘’‘
   姓名  年龄 性别   工资  省份
0  张三  23100  福建
1  李四  27200  浙江
2  王二  26300  广东
--=--
     工资             性别          
省份   广东   浙江   福建   广东   浙江   福建
姓名                              
张三  NaN  NaN  100  NaN  NaN    男
李四  NaN  200  NaN  NaN    女  NaN
王二  300  NaN  NaN    女  NaN  NaN
’‘’



pandas dataframe 分组聚合时,分组组名并入列的方法

import pandas as pd
data = pd.read_excel("数据.xlsx")
df = data[["名称","准确率"]]
result = df.groupby(df["名称"],as_index=False).sum()	# 这里要使用as_index参数

complete = result.loc[result["准确率"]>=1]
incomplete = result.loc[result["准确率"]<1]
newc=pd.DataFrame(complete)
print(newc)



between的使用

between是针对某一列(series)进行计算的

series[series.between(n1,n2,inclusive=True)].count()
# inclusive代表包括端点



两个df上下合并

result_df = df1.append(df2)



df增加一列

data_list = []
df["新的一列"] = data_list
# 默认加载最后一列
# 如果需要插入到指定位置
df.insert(第几列, '列名', data_list)
# 最后一列:len(df.columns)



版权声明:本文为qq_43224059原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。