Pandas常用操作(一)

安装pandas

pip install pandas

创建Series

Series是pandas中的一种数据类型,类似于字典,是一种一维的、含索引的数据类型,当然index索引也可以自定义。

import pandas as pd
import random
import string
# 创建Series,传入列表作为value值,index值默认
t0 = pd.Series([1,2,3,4])
print(t0)
print(type(t0))

# 指定index索引为a,b,c,d,e
t1 = pd.Series([random.randint(2,9) for i in range(5)],index=list('abcde'))
print(t1)

# 通过字典创建,字典的key值会转化为Series的index
# value值作为Series的value值
t_dict = {'猪头':24,'haha':True,23:'OK'}
t2 = pd.Series(t_dict)
print(t2)

# string.ascii_uppercase[i]表示第i个大写字母
_t = {string.ascii_uppercase[i]:i for i in range(0,11)}
t3 = pd.Series(_t)
# 修改value的数据类型,修改之后要重新赋值
t3 = t3.astype(float)
print(t3)

# 这里Series在创建时已经传入了index和value,而string.ascii_uppercase[5:15]
# 和index有交叉的部分,这里t4最终得到的是交叉部分的值以及剩余index对应NaN值
t4 = pd.Series(_t,index=list(string.ascii_uppercase[5:15]))
print(t4)

# 根据索引取值
print(t4['G'])

# 这种写法会将index也写出来,这是按行取值
print(t4[0:1])
print(t4[:2])

# 取index,结果是一个pandas.core.indexes.base.Index类型,并且是可迭代对象
print(t4.index)
print(list(t4.index))           # 强制类型转换为列表

# 取value值,为numpy.ndarray类型
print(t4.values)
print(type(t4.values))

# pandas的where方法和numpy的where方法有所区别
# numpy的where方法用于修改数组,t.where(t>10,20)将t中所有大于10的数修改为20
# pandas的where方法用于筛选,t.where(t>10,20),将t中所有大于10的数不做改变,其余数改称20

pandas读取数据

import pandas as pd
import numpy as np
from pymongo import MongoClient

# numpy的loadtxt方法不仅仅可以读csv文件,以下是numpy读取方式
path = './haha.txt'
# 需指定分隔符,读取后的数据类型
t = np.loadtxt(path,delimiter=',',dtype=int)
print(t)

# pandas读取csv文件,不需要指定','或者其他符号作为分隔符,也不需要指定读取后的类型
#与numpy读取的区别是,如果csv文件中有多列,读取出来的结果是DataFrame类型,并且第一行默认作为列索引columns
t = pd.read_csv('./youtube_video_data/GB_video_data_numbers.csv')
print(t)

创建DataFrame

import numpy as np
import pandas as pd

# 创建DataFrame,3行4列,使用默认的行索引和列索引
t = pd.DataFrame(np.arange(1,13).reshape(3,4))
print(t)

# 传入index和columns参数
t = pd.DataFrame(np.arange(1,13).reshape((3,4)),index=['a','b','c'],columns=list('wxyz'))
print(t)

# 传入字典创建DataFrame,在创建Series时,字典的key会作为索引,而创建DataFrame时
# 字典的key会作为列索引,字典value值列表会被拆成多行
d1 = {'name':['zhangsan','lisi'],'age':[23,24],'prop':['计算机','中医学']}

# 这里字典已经包含columns参数,传入其他的columns会创建为NaN
t = pd.DataFrame(d1,index=['z','l'],columns=[1,2,3])      

# 第二种字典传入方式,传入字典的列表,每一个字典会被当做一天记录
# 字典的key值仍然是columns参数
d2 = [{'name':'wangjian','age':22,'prop':'计算机'},{'name':'zhumengya','age':23,'prop':'计算机'},{'haha':'haha'}]
t = pd.DataFrame(d2)
print(t)

# DataFrame的属性
print(t.shape)      # DataFrame的形状(行,列)
print(t.index)      # 行键
print(t.columns)    # 列键,class 'pandas.core.indexes.numeric.Int64Index'类型
print(t.values)     # 包含的值,是ndarray类型
print(t.dtypes)     # value值的类型
print(t.ndim)       # 维度

# 读取文件操作
csvinfo = pd.read_csv('./youtube_video_data/GBvideos.csv')

# 显示头几行
print(csvinfo.head(2))
print('-*'*50)
# 显示尾几行
print(csvinfo.tail(2))

# 展示DataFrame的info,会输出columns的信息,m*n维的信息,占用内存多少的信息
print(csvinfo.info())

# DataFrame的describe函数,用于展示DataFrame的数字列统计信息
# 只会统计时数字类型的列,否则无意义
print(csvinfo.describe())

# 对DataFrame进行排序,按照likes列进行排序,不升序(即降序)排列
csvinfo = csvinfo.sort_values(by='likes',ascending=False)
print(csvinfo.head(5))

DataFrame切片操作

import pandas as pd
import numpy as np

t0 = pd.read_csv('./youtube_video_data/GBvideos.csv')

# 输出前20行,结果为DataFrame
# 注意不能直接写t0[2],里面不能直接写数字,直接写会被认为是取列,写数字的集合也不行,除非列中有该索引,否则报错
print(t0[:20])

# 同时对行列操作,当只选取一列时,结果类型为Series
# 先取行和先取列结果是一样的
# 总结:取行就使用':数字'的形式,取列就使用字符串索引
print(t0[:20]['video_id'])			# Series类型
print(t0['date'][:3])				# Series类型,先列再行

t1 = pd.DataFrame(np.arange(1,16).reshape((3,5)),index=list('abc'),columns=[1,2,3,4,5])
print(t1)

# 直接写数字被认为是取列操作,结果为Series类型,可以使用['a','b']来取多行
# 如果取不连续的多行,一般先取列,再用[['a','b']]这种形式取行
# 但是当行索引为数字时使用[,,]传入的方式会报错,除非改写成[:2]这种形式
print(t1[1][['a','b']])

print('-*'*40)
# 总结:取多列,传入列表用逗号隔开[,,],只能用这种形式
# 注意,行只能用[:2]和非数字的列表这种形式
# print(t1[[3,4]])			# 取列索引为3和4的列

# 不容易混淆更方便的方法,使用loc定位,loc定位时必须根据索引来,而不能使用数字
# 逗号前面是行索引,后面是列索引
# 'a','b'行和1,2列的交集
print(t1.loc[['a','b'],[1,2]])

# 注意下面这种情况,a,b,c行全会被选出来
print(t1.loc['a':'c',[1,2]])

# 使用数字进行切片,iloc方法只能用数字切片,不能是使用行列索引
print(t1.iloc[1,2])

# 和numpy有所区别,这里取出的是第1,2行和2,3列的交叉部分,其余和numpy数字切片一样操作
# 可直接进行赋值操作,可直接赋值np.nan不用类型转换,DataFrame会自动进行转换
t1.iloc[[1,2],[2,3]] = 30
print(t1)

Bool索引和NaN的处理方法

import pandas as pd
import numpy as np
import random

t = pd.read_csv('./DogName.csv')
# print(t)

# 布尔索引,筛选t['count']>100的那些行
print(t[t['count']>100])
# print(t[80<t['count']<100])                   # 不能像Python一样连写

# &表示与,必须要用括号括起来,|表示或运算
# 单独80<t['count']是一个Bool型的Series序列
print(t[(80<t['count']) & (t['count']<100)])

# 输出每只狗狗名字的长度,pandas.core.series.Series类型
print(t['DogName'].str.len())

# t['DogName'].str.很多方法
# 其余较常用的有.str.split('切割符号'),用于将字符串转换成列表,最后输出的形式是Series,index和该列切分后的列表[]
# .str.split('切割符号').tolist,可以加个整个Series的value部分转换为一个大列表,其中嵌套小列表


# 缺失数据处理
t1 = pd.DataFrame(np.array([random.randint(1,10) for i in range(15)]).reshape((3,5)),index=list('abc'),columns=list('vwxyz'))
# 定位数据并赋值nan
t1.loc['b':,'v':'w'] = np.nan
print(t1)

# 下面这样赋值会报警告SettingWithCopyWarning,而且内容并未修改,最好是使用loc或者iloc进行修改
t1[:1]['z'] = np.nan
print(t1)

# 判断是否含有nan
print(pd.isnull(t1))
# 判断是否不含null
print(pd.notnull(t1))

# 当how = 'any'时表示只要含有nan就删除行
# 当how = 'all'时表示该行全为nan时才删除
# inplace属性表示是否进行原地操作,即直接对t1进行修改
print(t1.dropna(axis=0,how='any'))

# 将t1中的nan值填充为20
t1.fillna(20,inplace=True)
print(t1)

# 输出t1的均值,注意pandas求均值时和numpy有所不同,pandas求均值会自动将nan数据过滤掉,求方差等亦是
print(t1.mean())
# 将nan值用均值填充,这里填充时填充的是每一列的均值,并非所有值的均值
t1.fillna(t1.mean(),inplace=True)
print(t1)
# 单独对某一字段进行nan填充
t1['v'].fillna(t1['v'].mean(),inplace=True)
print(t1)

Pandas常用统计方法

import pandas as pd
import numpy as np
import random

path = './movies.csv'
df = pd.read_csv(path)
# 输出DataFrame基本信息
print(df.info())

# 输出第一行查看格式
print(df.head(1))

# 获取平均分
print(df['Rating'].mean())

# 获取导演总人数
# tolist方法是Series类的特有方法,df['Director']已经切片为Series类,故可以用tolist方法
print(len(set(df['Director'].tolist())))
# 另一种方法,这里unique方法也是Series类型特有的
print(len(df['Director'].unique()))

# 获取演员的人数
actor_list = df['Actors'].str.split(',').tolist()
# print(actor_list)               # 大链表嵌套小列表

# 记住下面这种双重循环展开的方式
actors = [i for j in actor_list for i in j]
# 另一种展开方式
# 这里actor_list由于有些含有nan值,导致不是矩形,直接传入ndarray会报错,正常情况下可有如下写法
# 报错:VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences
# actors = np.array(actor_list).flatten()

# 输出演员人数
print(len(set(actors)))

# 电影时长的最大最小值,实际上这些方法是对Series的values进行操作
print(df['Runtime (Minutes)'].max())    # 191分钟
print(df['Runtime (Minutes)'].min())    # 66分钟
print(df['Runtime (Minutes)'].argmax())    # Index索引:828
print(df['Runtime (Minutes)'].argmin())    # Index索引:793
print(df['Runtime (Minutes)'].median())     # 中位数111分钟

案例1:电影时长分布的统计

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from matplotlib import font_manager

# 自定义字体
myfont = font_manager.FontProperties(fname='C:\WINDOWS\FONTS\SIMKAI.TTF')

path = './movies.csv'
# 读出数据
df = pd.read_csv(path)
runtime = df['Runtime (Minutes)'].tolist()
rating = df['Rating'].tolist()

# # 均为1000条数据
# print(len(runtime),len(rating))

# 画布
plt.figure(figsize=(20,8),dpi=80)

# 大致分布在60--200,划分成14列
numbins = 14

# 绘图,下面这两种写法相同,hist为直方图
# plt.hist(runtime,range(60,201,10))
plt.hist(runtime,range=(60,200),bins=numbins)

# 设置x轴
plt.xticks(range(60,201,10))
plt.yticks(range(0,251,25))

# 设置标题
plt.title('电影时长分布图',fontproperties=myfont,size=18)
plt.xlabel('时长(minute)',fontproperties=myfont,size=16)
plt.ylabel('电影数(部)',fontproperties=myfont,size=16)

# 展示
plt.show()

案例2:电影每种分类的部数统计

思想:每种电影可对应多个分类,首先统计出所有电影可能的分类有哪些,然后创建一个DataFrame,index指示每一部电影,columns指示所有可能的电影类别,初始化时该DataFrame所有数据均为0
然后遍历每部电影,发现该电影属于哪些分类,便将该分类置为1,最后按列统计该DataFrame的和即为每类电影的部数

import numpy as np
import pandas as pd

path = './movies.csv'
# 读出数据
df = pd.read_csv(path)

# print(df['Genre'])
# 首先统计共有多少中不同的分类
# 这里每种电影可以属于多个分类,将该‘分类信息’的字符串拆开
genre_list = df['Genre'].str.split(',').tolist()
# 求出共多少类电影
genre = list(set([i for j in genre_list for i in j]))
print(genre)

# 统计数据
# 首先创建一个二维数组,初始化均为0,列索引columns就使用genre 列表即可
sta = pd.DataFrame(np.zeros((df.shape[0],len(genre))),columns=genre,dtype=int)

# 遍历df统计信息,下面这种写法写麻烦了
# k = 0
# for i in genre_list:
#     for j in i:
#         sta.loc[k][j] = 1
#         pass
#     k += 1
#     pass

# 另一种统计方法,这里genre_list[i]仍然为列表,直接给一行多列赋值1
for i in range(df.shape[0]):
    sta.loc[i,genre_list[i]] = 1
    pass


# 已经遍历完成
print(sta)
# 统计各列之和即为某类电影共多少部,下面方法较麻烦
# for i in genre:
#     print('{}:{}部'.format(i, sta[i].sum()))

# 另一种方法
print(sta.sum(axis=0))

使用的csv文件

可免费到下面的链接下载
点我下载csv文件

猜你喜欢

转载自blog.csdn.net/tiaochewang219/article/details/107465597