Pandas 是一个开放源码、BSD 许可的库,提供高性能、易于使用的数据结构和数据分析工具。pandas基础就是Dataframe,生成二维表。
pandas有两种生成Dataframe的方法。
第一种是以字典的形式先准备好每一列的数据,用Dataframe生成表格,再用index方法生成行索引(就是我们平常excel中的行名)
import pandas as pd
# 准备好列数据,注意字典的key为列名,value可以是一个列表
df = pd.Dataframe({'Chinese': [60, 70], 'Egnlish': [50, 60]})
print(df)
# 使用index方法加入索引(行名)
df.index = ['xiaoming', 'xiaohua']
print(df)
第二种是以列表的方式准备好数据、列索引、行索引,使用关键字参数的方式建立表格
import pandas # 准备好数据、列名、索引 data = [[60, 70], [50, 60]] columns = ['English', 'Chinese'] index = ['xiaoming', 'xiaohua'] # 关键字传参,data为数据,columns为列名,index为索引 df = pd.Dataframe(data=data, columns=columns, index=index) print(df) print(df['English'])
当然如果不嫌麻烦,还可以先传数据,再传列索引和行索引
import pandas s = pd.Series([60, 70]) print(s) s = pd.Series(data=[60, 70], index=['xiaoming', 'xiaohua']) print(s)
Pandas将Dataframe输出成excel、csv、json可太方便了,直接to_excel,to_csv,to_json即可
import pandas as pd
data = [[60, 70], [50, 60]]
columns = ['English', 'Chinese']
index = ['xiaoming', 'xiaohua']
df = pd.Dataframe(data=data, columns=columns, index=index)
df.to_excel('C:/target.xlsx', sheet_name='Sheet1', index=False)
#写入excel index = False会抛弃行索引,比下面的两个多了sheet_name
df.to_csv('C:/target.csv')
#写入csv
df.to_json('C:/target.json')
#写入json
同样要读取这三类文件也很简单,直接read_excel,read_csv,read_json即可。注意read_json的时候如果json是GBK编码会报错。尝试了好几种方法都没能解决,不知道有没有大佬能指点一下。
import pandas as pd
a = pd.read_excel('C:/target.xlsx', sheet_name='Sheet1', usecols=[0,1,2])
print(a)
# 读取excel, usecols表示要读取哪几列进来
b = pd.read_csv('C:/target.csv', index_col=0)
print(b)
# 读取csv, index_col表示哪一列为列索引
c = pd.read_json('C:/target.json')
print(c)
# 读取json
注意在读取excel和csv过程中,如果没有参数,则默认会添加行索引,列索引则不会。如果要指定行索引,就要用index_col=0参数。json数据不存在这个问题。usecols可以传一个列表进来,表示要读取哪几列。对数据多的时候特别有用。usecols还可以用列名!
df = pd.read_excel('data/1月.xlsx', usecols=['收货人姓名'])
pandas还可以直接爬取网络上规整的表格数据,比如nba球员薪酬
NBA Player Salaries - National Basketball Association - ESPN
import pandas as pd
df = pd.Dataframe()
for i in range(1, 14):
url = 'http://www.espn.com/nba/salaries/_/page/' + str(i)
# read_html,把html里面的table给读取过来
data = pd.read_html(url)
# append可以向对象添加新的行
# ignore_index默认为False,如果为True,则不适用索引
df = df.append(data, ignore_index=True)
# 原网站隔一段数据重复了以下标题,所以代码作了以下处理
# startswith表示数据以什么开头。in df[3]表示第三列
# 意思是取第三列中有$开头的数据,去掉了所有列名
df = df[[x.startswith("$") for x in df[3]]]
print(df)
# 手动把列名加回去header
df.to_csv('NBATEST.csv', header=['RK', 'NAME', 'TEAM', 'SALARY'], index=False)
访问Dataframe中数据
详情请看代码注释部分
import pandas as pd
df = pd.read_csv("NBATEST.csv")
print(df) # 整个表格
# 传统获取数据
print(df.NAME) # 获取NAME这列
print(df['NAME']) # 获取NAME这列
print(df['NAME'][0]) # 获取NAME这列的第一个数据
# 使用pd的iloc
print(df.iloc[0]) # 获取第一行数据
print(df.iloc[:, 1]) # 获取第一列数据
print(df.iloc[:3, 1]) # 获取前3个第一列数据
print(df.iloc[[0, 2, 3], 1]) # 获取索引为0,2,3的第一列数据
print(df.iloc[-5:]) # 获取倒数5行数据
# 使用pd的loc属性
print(df.loc[:,['NAME','TEAM']]) # 获取NAME和TEAM列所有行的数据
# 条件选择
print(df.loc[df.TEAM=='Washington Wizards']) # 获取TEAM名为'Washington Wizards'的数据
print(df.loc[(df.TEAM=='Washington Wizards') & (df.RK>100)]) # 获取TEAM名为'Washington Wizards',且RK>100的数据
print(df.loc[df.TEAM.isin(['Washington Wizards','Denver Nuggets'])]) # 获取TEAM名为'Washington Wizards',或者是'Denver Nuggets'的数据
print(df.loc[df.TEAM.notnull()]) # 获取所有非空数据
pandas的describe方法
pandas有个很牛的describe,可以做很多数据统计
import pandas as pd
reviews = pd.read_csv("data/Wine Reviews-data/winemag-data-130k-v2.csv")
print(reviews.head()) # 获取前5行
print(reviews.points.describe())
print(reviews.points.describe(percentiles=[.70,.9]))
print(reviews.taster_name.describe())
输出结果:
print(reviews.points.describe()) ''' 输出结果: [5 rows x 14 columns] count 129971.000000 计数 mean 88.447138 平均值 std 3.039730 标准差 min 80.000000 最小值 25% 86.000000 达到前25%所需分数 50% 88.000000 达到前50%所需分数 75% 91.000000 达到前75%所需分数 max 100.000000 最大值 Name: points, dtype: float64 '''
print(reviews.points.describe(percentiles=[.70,.9])) ''' 输出结果 这里就是定义了前70%和前90%所需分数 count 129971.000000 mean 88.447138 std 3.039730 min 80.000000 50% 88.000000 70% 90.000000 90% 92.000000 max 100.000000 Name: points, dtype: float64 '''
print(reviews.taster_name.describe()) ''' 输出结果 这表格里面有个列taster_name,统计这列 count 103727 计数 unique 19 唯一值的数量 top Roger Voss 出现频率最高的数据 freq 25514 最高频率的出现次数 Name: taster_name, dtype: object '''pandas批量修改局部
直接修改(会警告不安全)
import pandas as pd
df = pd.read_csv('data/NBA.csv')
# 把所有空数据都改成OK
df.TEAM[df.TEAM.isnull()]='OK'
# 这里to_string()的意思是所有数据,如果不加,则只打印前5行,后5行
print(df.to_string())
df.to_csv('data/NBA.csv')
使用fillna修改所有空值
import pandas as pd
df = pd.read_csv('data/NBA.csv')
df.fillna('OK2', inplace=True)
# inplace=True表示直接操作本身,如果没有这句,则需要df = df.fillna('OK2')
print(df.to_string())
df.to_csv('data/NBA.csv')
使用map或apply进行修改
注意apply不需要传参,只需要写函数名
import pandas as pd
# 因为这里我的csv数据类似于json,使用;间隔,每一行都是一整个字符串
# 所以这里加了sep=';'表示使用;作为分隔符
reviews = pd.read_csv("data/winemag-data_first150k.csv", sep=';')
RPM = reviews.points.mean() # 平均值
'''
map可以替换数据,全部替换成平均值。
lambda p: p - RPM 匿名函数相当于:
def aa(p):
return(p - RPM)
'''
print(reviews.points.map(lambda p: p - RPM))
# 使用apply方法,则不用传参,只要写个函数名
def remean_points(points):
return (points - RPM)
print(reviews.points.apply(remean_points))
# print(reviews['points'].apply(remean_points)) # 也可以这样写
groupby可以对数据进行分组
import pandas as pd
reviews = pd.read_csv("data/winemag-data_first150k.csv", sep=';')
print(reviews.groupby('points').points.count()) # 以points分组,统计每组points的数量
print(reviews.groupby('points').price.min()) # 以points分组,统计每组price的最小值
print(reviews.groupby('winery').apply(lambda df: df.title.iloc[0])) # 以winery分组,列出每个组title的第一个值
print(reviews.groupby(['country','province']).apply(lambda df: df.loc[df.points.idxmax()])) # 根据国家和省份分组,选出points最高的索引。idxmax表示最大值对应的索引
print(reviews.groupby("country").price.agg(['mean','min', 'max'])) # 以国家分组,并统计均值、最大值、最小值
# 以points排序,降序
df = reviews.sort_values(by='points', ascending=False)
print(df[['country','price','points']])
# 以points作为降序排名,method为first表示出现数据相同,原表中顺序如何排名也如何。为min,相同数据都取最小排名。为max,相同数据都取最大排名
df['RANK'] = df['points'].rank(method='min', ascending=False)
print(df.loc[:, ['points', 'RANK']])
pandas处理缺失值
NaN:表示没有数值。python认为NaN类型为float64
pd.isnull()和pd.notnull()可以检索出缺失数据
fillna()函数可以替换na的值
import pandas as pd
reviews = pd.read_csv("data/Wine Reviews-data/winemag-data-130k-v2.csv")
# 检索出country这列中所有空数据
print(reviews[pd.isnull(reviews.country)])
# 把所有空数据填上Unknown
reviews_region_2=reviews.fillna('Unknown')
print(reviews_region_2.loc[reviews_region_2.country=='Unknown',['country','title']])
replace替换数据
import pandas as pd
reviews = pd.read_csv("data/Wine Reviews-data/winemag-data-130k-v2.csv")
# 把表里taster_twitter_handle这列中@keriokeefe全部替换成@kerio
temp2 = reviews.taster_twitter_handle.replace("@keriokeefe","@kerio")
print(temp2)
pandas数据的增删修
import pandas as pd
# 更改print显示列数
pd.set_option('display.max_colum',500)
pd.set_option('display.width',1000)
reviews = pd.read_csv('data/Wine Reviews-data/winemag-data-130k-v2.csv')
print(reviews.head(20)) # 显示前20项
# 重命名列/索引
print(reviews.rename(columns={'points':'score'}))
print(reviews.rename(index={0:'first entry',1:'second entry'}))
# 删除行或列
print(reviews.drop('country',axis=1)) #axis=1表示列,0表示行。删除列要用列名,删除行要用索引名
print(reviews.shape) # 显示表的结构(行数列数)
print(reviews[pd.isna().any(axis=1)]) # 显示所有NaN的行
reviews.dropna(inplace=True) # 删除所有NaN的行
reviews.dropna(axis=0, how='any', inplace=True) # 删除所有含有NaN的列
reviews.dropna(axis=0, subset=['region2'],inplace=True) # 删除特定列为NaN的行,axis=0表示行
reviews.dropna(axis =1, inplace=True) # 删除有缺失值的列



