pandas操作指南(超级详细!!!)

引言:最近pandas好久不用忘光光先写一点备着,以后实时更新防止自己忘掉,都是pandas最基本的概念,但是和别的博客有点不同,里面有着大量的实例可以帮助大家更好的理解pandas库的各个函数而不是枯燥的概念

pandas常用操作

  • 前期准备
  • 文件读取和保存
    • 普通保存
    • 类型切换保存
    • 保存时的设置参数
    • 大文件读取
    • 分类型读取
  • 数据处理
    • 数据前期预处理
    • 数据后期预处理(哑标,大小写,随机重排序)
    • 数据类型转换
    • 数据选取
    • 数据切割划分
    • 数据缺失
    • 数据填充
    • 数据去重
    • 数据替换
    • 数据分组
    • 数据聚合
    • 数据规整
      • 数据合并连接
      • 数据索引分层
      • 重命名轴索引
    • 数据排序
    • apply和map和lambda函数
    • 时间处理
      • 时间序列基础
      • 日期解析和提取
      • 时区转换
    • 正则表达式
    • 另外一些函数(sum,count,add,fill)
  • 典型筛选案例
    • 自定义函数
    • 函数组合
    • 其他(重采样,take,data-dict转换等)
  • numpy基础

前期准备

这里先提供一组数据集

data = {
    'state':['Ohio2','Ohio2','Ohio2','Nevada2','Nevada2'],
    'year':[2002,2012,2022,2012,2022],
    'pop':[1.52,1.72,3.62,2.42,2.92],
    'salary':['5000K/MTH - 20000K/MTH', '12K/MTH - 19K/MTH',
       '4000K/MTH - 6000K/MTH', '14000K/MTH - 22000K/MTH','8000K/MTH - 20000K/MTH']
}
data = pd.DataFrame(data)

文件读取和保存

普通保存

#读取
data = pd.read_csv(r'E:\vscode_code\练习\文本练习\东方火锅.csv')

#保存,这里保存为txt模式,所以参数要稍微变化
#显示以制表符分割,否则保存就是按照csv模式的逗号分割而不是txt的制表符分割
data.to_csv(r'E:\vscode_code\练习\文本练习\1.txt', sep = '\t', index = False)
#普通的csv保存不需要制表符分割,因为他本身是以逗号进行分割
data.to_csv(r'E:\vscode_code\练习\文本练习\1.csv', index = False)

类型切换保存

#Excel文件
data = pd.read_excel(r'E:\vscode_code\数据分析第二版\数据保存\文件测试\test.xlsx','Sheet1',index_col=0)
#保存为csv
data.to_csv(r'E:\vscode_code\数据分析第二版\数据保存\文件测试\test.csv',encoding='utf-8')
#这个时候一定要加'header=None', 这样读进来的列名就是系统默认的0,1,2... 序列号,不然会把文件内容当做列名
data = pd.read_csv(r'E:\vscode_code\数据分析第二版\数据保存\文件测试\test.csv', header=None)

保存时的设置参数

#第一: 一定要使用header = false, 不然的话保存数据集的时候,会自动使用0-n作为数据的列名。但如果是字典,就使用键值当索引
#第二: 一定也要使用index=False, 不然的话保存数据的时候,会自动加上一个索引列。
#第三: 如果不需要覆盖原文件, 用mode='a',默认是覆盖原文件的
#这里因为是字典带有键值,所以还是header=true,但是如果需要

data.to_csv(r'E:\vscode_code\数据分析第二版\数据保存\1.csv', index=False, header=True)
data2.to_csv(r'E:\vscode_code\数据分析第二版\数据保存\1.csv', index=False, mode='a', header=False)
data3.to_csv(r'E:\vscode_code\数据分析第二版\数据保存\1.csv', index=False, mode='a', header=False)

大文件读取

在python中使用基本的pandas.read_csv打开文件时:MemoryError

import pandas as pd 

def knn():
#创建一个新的dataframe数据,用来append
    frame = pd.DataFrame()
    # 读取数据
    file_path = r'E:\vscode_code\多线程\双色球\qiu2.csv'
       
    reader = pd.read_csv(file_path, chunksize=20)    # 每块为20条数据(index)
    
    for chunk in reader:
    #这里需要重新设置索引,不然索引可能会重复
        frame = frame.append(chunk).reset_index(drop=True)
        #print(chunk.head())
        #只输出一块,把这个去掉就是所有数据了
        #break
    print(frame.describe())
 
if __name__ == '__main__':
    knn()

分类型读取

df=pd.read_csv('text.csv', dtype={'code':str}
''' 
这样,把你要转换的列的名字设定好, “code”列中的数据读取为str 
这样,读取到的数据就是按照我们的要求的了。否则,类似001会读取成为1
'''

数据处理

数据前期预处理

#输出文件类型
print(data.info())

#输出所包含的不重复内容
print(data['year'].unique())

#数据的答题内容包含列名和数据个数
#但是这里经过测试,只有数字类型的才会被统计
print(data.describe())

#默认前五个输出
print(data.head())

#默认后五个输出
print(data.tail())

#其他
data.index
data.columns
data.values

#注意点
sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000}
obj3 = pd.Series(sdata)
#单个元素的字典直接转为DataFrame时,程序会报错,需要适当做些转换,指定行索引或者列索引才行
#sdata2 = {'Ohio': [35000], 'Texas': [71000], 'Oregon': [16000], 'Utah': [5000]}
#obj4 = pd.DataFrame(sdata2)
#print(obj3)
#print(obj4)
states = ['California', 'Ohio', 'Oregon', 'Texas']
obj4 = pd.Series(sdata, index=states)

数据后期预处理(哑标,大小写,随机重排序)

data = pd.DataFrame({'food': ['bacon', 'pulled pork', 'bacon',
                               'Pastrami', 'corned beef', 'Bacon',
                               'pastrami', 'honey ham', 'nova lox'],
                      'ounces': [4, 3, 12, 6, 7.5, 8, 3, 5, 6]})
#把他全部转化为小写字母
lowercased = data['food'].str.lower()


#通过需要排列的轴的长度调用permutation,可产生一个表示新顺序的整数数组:(permuting,随机重排序)
samper = np.random.permutation(5)
print(samper)
#take函数用以获取对应索引的信息
df.take(samper)

#计算指标/哑变量#########################################
#将分类变量(categorical variable)转换为“哑变量”或“指标矩阵”。
df = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'b'],
                   'data1': range(6)})
#print(df)
#print(pd.get_dummies(df['key']))

#给指标DataFrame的列加上一个前缀,以便能够跟其他数据进行合并
dummies = pd.get_dummies(df['key'], prefix='key')
#print(dummies)

数据类型转换

data = {'a':['1','2','3'],'b':['4','5','6']}
data = pd.DataFrame(data)
#print(data)

#这是修改两种数据类型的方法
pd.to_numeric(data['a'], errors='coerce')
print(type(data.iloc[0,1]))
#必须要经过赋值才能够实现
data['c'] = pd.to_numeric(data['a'], errors='coerce')
print(data.iloc[2,2])
print(type(data.iloc[2,2]))
data['b'] = data['b'].astype('int64')
print(data.iloc[2,1])
print(type(data.iloc[2,1]))

数据选取

import pandas as pd 
import numpy as np 

'''
iloc主要使用数字来索引数据,而不能使用字符型的标签来索引数据。
而loc则刚好相反,只能使用字符型标签来索引数据,不能使用数字来索引数据,
不过有特殊情况,当数据框dataframe的行标签或者列标签为数字,loc就可以来其来索引。
''' 

df=pd.DataFrame(np.arange(0,60,2).reshape(10,3),columns=list('abc'))
print(df.loc[0,['a', 'b']])

data = {
    'state':['Ohio1','Ohio1','Ohio2','Nevada3','Nevada3'],
    'year':[2000,2001,2002,2001,2002],
    'pop':[1.5,1.7,3.6,2.4,2.9],
    'salary':['1000K/MTH - 20000K/MTH', '7K/MTH - 8K/MTH',
       '10000K/MTH - 16000K/MTH', '3K/MTH - 5K/MTH', '7K/MTH - 12K/MTH',]
}
data = pd.DataFrame(data)
#报错原因:https://blog.csdn.net/niuniuyuh/article/details/76650904
#print(data.loc[0,1])
#print(data.loc[:,[0,3]])
#print(data.iloc[0:3,'state'])
print(data.loc[0:3,'state'])
print(data.iloc[0:3,0:3])
print(data.iloc[:,[0,3]])
#print(data.iloc([0,3]))  这句是错的,因为参数没有指定完全

data.index = ['a','b','c','d','e']
#报错原因:https://blog.csdn.net/niuniuyuh/article/details/76650904
#print(data.loc[0:3,'state'])
print(data.loc['a'])
print(data.loc[['a','b'], 'state'])

#索引的其他用法################################3
#这两个索引函数也适用于一个标签或多个标签的切片:
#print(data.loc[:'Utah', 'two'])
#上下两种用法一样
#print(data.iloc[:, :3][data.three > 5])
#print(data.iloc[:, :3][data['three']>5])

#pandas可以对不同索引的对象进行算术运算。在将对象相加时,如果存在不同的索引对,则结果的索引就是该索引对的并集。
s1 = pd.Series([7.3, -2.5, '', 1.5], index=['a', 'c', 'd', 'e'])
s2 = pd.Series([-2.1, 3.6, -1.5, 4, 3.1],index=['a', 'c', 'e', 'f', 'g'])
#print(s1 + s2)

数据切割划分

#离散化和面元划分#############################
ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]
bins = [18, 25, 35, 60, 100]
cats = pd.cut(ages,bins)
#print(pd.value_counts(cats))
#你可以通过传递一个列表或数组到labels,设置自己的面元名称:
group_names = ['Youth', 'YoungAdult', 'MiddleAged', 'Senior']
pd.cut(ages, bins, labels=group_names)
#qcut是一个非常类似于cut的函数,它可以根据样本分位数对数据进行面元划分。

数据缺失

data.drop(data[data['标题'].isnull()].index, inplace = True)

#若原处是空字符串还需要用np.nan替换,因为dropna只对np.nan处理
data.replace(to_replace=r'',value=np.nan,regex=True,inplace=True)
#注意下面两种的区别,第一个只对某一列处理,整体没变
data['标题'].dropna(axis = 0, inplace = True)
#第二个才是对整体的处理
data.dropna(axis = 0,subset = ['标题'], inplace = True)
#传入how='all'将只丢弃全为NA的那些行:
data.dropna(how='all')


数据填充

#填充################################
data.fillna(0)
#若是通过一个字典调用fillna,就可以实现对不同的列填充不同的值:
data.fillna({1: 0.5, 2: 0})
#默认返回新对象,若对现有对象修改,用inplace参数
data.fillna(0, inplace=True)
#里面还有别的参数可以了解

数据去重

#去重
#输出的只有state这一列
print(frame['state'].duplicated())
print(frame['state'].drop_duplicates())

#输出的是经过去重后所有的数据
print(frame.drop_duplicates(['state']))
#保留最后一个
print(frame.drop_duplicates(['state'], keep='last'))

数据替换

#替换
#可以用字典对多个值进行替换
frame['year'].replace({2002:'1', 2012:'2'}, inplace=True)
frame['state'].replace({'Ohio2':'1', 'Nevada2':'2'}, inplace=True)

#替换#################################
#map可用于修改对象的数据子集,而replace则提供了一种实现该功能的更简单、更灵活的方式
data = pd.Series([1., -999., 2., -999., -1000., 3.])
#一次性替换多个值,可以传入一个由待替换值组成的列表以及一个替换值
data.replace([-999, -1000], np.nan)
#要让每个值有不同的替换值,可以传递一个替换列表:
data.replace([-999, -1000], [np.nan, 0])
#传入的参数也可以是字典:
data.replace({-999: np.nan, -1000: 0})

#针对csv的replace需要先转化成str
print(data['标题链接'].str.replace('www', '').head())

数据分组

import pandas as pd
import numpy as np

df = pd.DataFrame({'key1' : ['a', 'a', 'b', 'b', 'a'],
                   'key2' : ['one', 'two', 'one', 'two', 'one'],
                   'data1' : np.random.randn(5),
                   'data2' : np.random.randn(5)})
#group之后只是一个对象,可以对这个对象进行一系列操作
grouped = df['data1'].groupby(df['key1'])
means = df['key2'].groupby(df['key1'])
count = df['key1'].groupby(df['key2'])
#print(means)

states = np.array(['Ohio', 'California', 'California', 'Ohio', 'Ohio'])
#print(df['data1'].groupby([states]).mean())

#GroupBy的size方法,任何分组关键词中的缺失值,都会被从结果中除去。
#size跟count的区别: size计数时包含NaN值,而count不包含NaN值
#https://www.cnblogs.com/zknublx/p/12048410.html
print(df.groupby(['key1', 'key2']).size())

"""
#GroupBy对象支持迭代,可以产生一组二元元组(由分组名和数据块组成)
for name,group in grouped:
    print(name)
    print(group)
""" 
   
#mapping传递
people = pd.DataFrame(np.random.randn(5, 5),
                      columns=['a', 'b', 'c', 'd', 'e'],
                      index=['Joe', 'Steve', 'Wes', 'Jim', 'Travis'])
#你可以计算一个字符串长度的数组,更简单的方法是传入len函数:
#print(people.groupby(len).sum())

mapping = {'a': 'red', 'b': 'red', 'c': 'blue',
           'd': 'blue', 'e': 'red', 'f' : 'orange'}

by_column = people.groupby(mapping, axis=1)
by_column.sum()

#Series也有同样的功能,它可以被看做一个固定大小的映射:
map_series = pd.Series(mapping)


#还可以利用sample函数
#分类,当分类类别数超过总数,可用replace参数
choices = pd.Series([5, 7, -1, 6, 4])
#print(choices.sample(10,replace=True))
draws = choices.sample(n=10, replace=True)

数据聚合

import pandas as pd
import numpy as np

people = pd.DataFrame(np.random.randn(5, 5),
                      columns=['a', 'b', 'c', 'd', 'e'],
                      index=['Joe', 'Steve', 'Wes', 'Jim', 'Travis'])

def peak_to_peak(arr):
    return arr.max() - arr.min()

#print(people.apply(peak_to_peak))
print(people.agg(peak_to_peak))

数据规整

数据合并连接

针对单独两列数据的合并,目前只想到用concat,merge一直报错

import pandas as pd 

"""
#这两个:一、concat:沿着一条轴,将多个对象堆叠到一起;二、merge:通过键拼接列,是对于dataframe的合并

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)
pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False,  
      keys=None, levels=None, names=None, verify_integrity=False, copy=True)

#https://blog.csdn.net/brucewong0516/article/details/82707492
#https://blog.csdn.net/gdkyxy2013/article/details/80785361
"""

#str.cat是针对于拼接而非合并
data = {
    'state':['Ohio1','Ohio1','Ohio2','Nevada3','Nevada3'],
    'year':[2000,2001,2002,2001,2002],
    'pop':[1.5,1.7,3.6,2.4,2.9],
    'salary':['1000K/MTH - 20000K/MTH', '7K/MTH - 8K/MTH',
       '10000K/MTH - 16000K/MTH', '3K/MTH - 5K/MTH', '7K/MTH - 12K/MTH',]
}
data = pd.DataFrame(data)

data['a'] = data['state'].str.cat(data['salary'], sep = '-')
#强制转化成了str之后就可以合并了
data['year_str'] = data['year'].astype('str')
data['b'] = data['state'].str.cat(data['year_str'], sep = '-')
print(data)
#另一组测试数据集
left = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
                       'A': ['A0', 'A1', 'A2', 'A3'],
                       'B': ['B0', 'B1', 'B2', 'B3']})
right = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
                        'C': ['C0', 'C1', 'C2', 'C3'],
                        'D': ['D0', 'D1', 'D2', 'D3']})
result = pd.merge(left, right)
print(result)
#针对单独两列数据的合并,目前只想到用concat,merge一直报错
result = pd.concat([left['A'], right['C']], axis = 1)

数据索引分层

import numpy as np 
import pandas as pd

data = pd.Series(np.random.randn(9),
                  index=[['a', 'a', 'a', 'b', 'b', 'c', 'c', 'd', 'd'],
                         [1, 2, 3, 1, 3, 1, 2, 2, 3]])
#print(data)
#通过unstack方法将这段数据重新安排到一个完整的DataFrame中:
#print(data.unstack())
#unstack的逆运算是stack:
data.unstack().stack()

#可以实现分层索引
frame = pd.DataFrame(np.arange(12).reshape((4, 3)),index=[['a', 'a', 'b', 'b'], [1, 2, 1, 2]],
                      columns=[['Ohio', 'Ohio', 'Colorado'],
                               ['Green', 'Red', 'Green']])
#各层也可以有名字
frame.index.names = ['key1', 'key2']
frame.columns.names = ['state', 'color']
                    

#使用DataFrame的列进行索引########################################
frame = pd.DataFrame({'a': range(7), 'b': range(7, 0, -1),
                       'c': ['one', 'one', 'one', 'two', 'two',
                             'two', 'two'],
                       'd': [0, 1, 2, 0, 1, 2, 3]})

#set_index函数会将其一个或多个列转换为行索引,并创建一个新的DataFrame:
frame2 = frame.set_index(['c', 'd'])
print(frame2)
#默认情况下,那些列会从DataFrame中移除,但也可以将其保留下来:
#frame.set_index(['c', 'd'], drop=False)

#1.reset_index
#reset_index可以还原索引,重新变为默认的整型索引 
frame3 = frame2.reset_index(level = ['c'])
print(frame3)
#内置参数drop可以把原索引列给删除
frame = frame.append(frame).reset_index(drop=True)
#2.reindex,其作用是创建一个新对象,它的数据符合新的索引
obj = pd.Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c'])
obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e'])

#sort_index:排序
obj=pd.Series([4,9,6,20,4],index=['d','a','e','b','c'])
#按obj的索引排序,默认升序,降序可在括号加ascending=False
print(obj.sort_index())

重命名轴索引

#重命名轴索引##########################
data = pd.DataFrame(np.arange(12).reshape((3, 4)),
                    index=['Ohio', 'Colorado', 'New York'],
                    columns=['one', 'two', 'three', 'four'])
#1.
transform = lambda x: x[:4].upper()
data.index.map(transform)
#data.rename()#内置参数

数据排序

#排序和排名
obj = pd.Series(range(4), index=['b', 'a', 'b', 'c'])
obj.sort_index()
#索引的is_unique属性可以告诉你它的值是否是唯一的:
#print(obj.index.is_unique)

apply和map和lambda函数

import pandas as pd 
'''
apply 用在dataframe上,用于对row或者column进行计算;

applymap 用于dataframe上,是元素级别的操作;

map (其实是python自带的)用于series上,是元素级别的操作。
'''
df = pd.DataFrame(np.random.randint(0,10,(4, 3)), columns=list('bde'), index=range(4))
f = lambda x: x.max() - x.min()
df.apply(f) 
df.apply(f,axis=1)  # 作用在一行上
df.apply(f,axis=0)  # 作用在一列上,axis=0可省略

#applymap: 作用在dataframe的每一个元素上
f2 = lambda x: x+1 if x%2==0 else x
df.applymap(f2)
##############################################
#声明匿名函数
f = lambda x: x.max() - x.min()
#这里的函数f,计算了一个Series的最大值和最小值的差
#在frame的每列都执行了一次。结果是一个Series,使用frame的列作为索引
frame.apply(f)

#如果传递axis='columns'到apply,这个函数会在每行执行:
frame.apply(f, axis='columns')

#map函数############################
data = pd.DataFrame({'food': ['bacon', 'pulled pork', 'bacon',
                               'Pastrami', 'corned beef', 'Bacon',
                               'pastrami', 'honey ham', 'nova lox'],
                      'ounces': [4, 3, 12, 6, 7.5, 8, 3, 5, 6]})
meat_to_animal = {
  'bacon': 'pig',
  'pulled pork': 'pig',
  'pastrami': 'cow',
  'corned beef': 'cow',
  'honey ham': 'pig',
  'nova lox': 'salmon'
}
#Series的map方法可以接受一个函数或含有映射关系的字典型对象
#传入对象
data['animal'] = lowercased.map(meat_to_animal)
#传入函数
data['food'].map(lambda x: meat_to_animal[x.lower()])

时间处理

时间序列基础

ps:'data.a.dt.year’里面的dt是针对series类型的数据,其他的只需要a.year即可

import pandas as pd 
import numpy as np 
from datetime import datetime
from datetime import timedelta
from dateutil.parser import parse
import pytz
import time


#字符串和datetime的互相转换
stamp = datetime(2011, 1, 3)
#print(stamp)
str(stamp)


#处理缺失值,配合pandas
idx = pd.to_datetime(datestrs + [None])
pd.isnull(idx)


#时间序列基础##############################################
#1.根据标签索引选取数据时,时间序列和其它的pandas.Series很像
dates = [datetime(2011, 1, 2), datetime(2011, 1, 5),
         datetime(2011, 1, 7), datetime(2011, 1, 8),
         datetime(2011, 1, 10), datetime(2011, 1, 12)]

ts = pd.Series(np.random.randn(6), index=dates)
#下面几种用法一样
ts[ts.index[4]]
ts['1/10/2011']
ts['20110110']
ts['2011-1-2']
ts[datetime(2011,1,2)]

#对于较长的时间序列,只需传入“年”或“年月”即可轻松选取数据的切片:
#数字个数和日期个数必须对应
longer_ts = pd.Series(np.random.randn(10),
                       index=pd.date_range('1/1/2000', periods=10))
#用法多样,只要索引符合规范
ts['2011-1-2':]
ts[datetime(2011, 1, 7):]
ts['1/6/2011':'1/11/2011']

#2.面这些操作对DataFrame也有效
#生成的就是一个DatetimeIndex
#pd.date_range(start='2012-04-01 12:56:31', periods=20, normalize=True) 
# 可以用start或end指定,normalize选项规范化(normalize)到午夜的时间戳
dates = pd.date_range('1/1/2000', periods=100, freq='W-WED')
long_df = pd.DataFrame(np.random.randn(100, 4),
                       index=dates,
                       columns=['Colorado', 'Texas',
                                    'New York', 'Ohio'])
long_df.loc['5-2001']

#产生重复
dates = pd.DatetimeIndex(['1/1/2000', '1/2/2000', '1/2/2000',
                           '1/2/2000', '1/3/2000'])
print(dates.dt.tz_convert('America/New_York'))

dup_ts = pd.Series(np.arange(5), index=dates)

#is_unique可以检查名字是否唯一
dup_ts.index.is_unique

#传入level=0:可以把重复的索引分开
grouped = dup_ts.groupby(level = 0)
grouped.mean()
grouped.count()


日期解析和提取

import pandas as pd 
import numpy as np 
from datetime import datetime
import time 


###################解析日期##########################
#datetime.strptime可以用这些格式化编码将字符串转换为日期:
#datetime.strptime是通过已知格式进行日期解析的最佳方式,只能处理单个数据
value = '2011-01-03'
value2 = datetime.strptime(value, '%Y-%m-%d')
datestrs = ['7/6/2011', '8/6/2011']
#中括号得加
value3 = [datetime.strptime(x, '%m/%d/%Y') for x in datestrs]
#print(value3)

#dateutil可以解析几乎所有人类能够理解的日期表示形式:
(parse('2011-01-03'))
(parse('Jan 31, 1997 10:45 PM'))
#在国际通用的格式中,日出现在月的前面很普遍,传入dayfirst=True
parse('6/12/2011', dayfirst=True)

#处理成组的日期
datestrs = ['2011-07-06 12:00:00', '2011-08-06 00:00:00']
pd.to_datetime(datestrs)
#带有中文的日期格式
#1.单个操作,如要多组数据,用for语句
value = '2011年1月3号'
value2 = datetime.strptime(value, '%Y年%m月%d号')

#2.多组操作,适用于dataframe类型
datestrs = ['2011-07-06 12:00:00', '2011-08-06 00:00:00']
datestr = pd.to_datetime(datestrs)
#针对有特定类型的日期类型
x = ['2011年7月6号', '2011年7月9号']
y = pd.to_datetime(x, format = '%Y年%m月%d号')

#################转换和提取#################
data = {
    'state':['Ohio2','Ohio2','Ohio2','Nevada2','Nevada2'],
    'year':['2002/1/2','2012/3/4','2022/5/6','2012/7/8','2022/9/10'],
    'pop':[1.52,1.72,3.62,2.42,2.92],
    'salary':['5000K/MTH - 20000K/MTH', '12K/MTH - 19K/MTH',
       '4000K/MTH - 6000K/MTH', '14000K/MTH - 22000K/MTH','8000K/MTH - 20000K/MTH'],
    'create_time':[1462451334, 1462451335, 1461231336, 1462451337, 1462451338]
}
data = pd.DataFrame(data)
data['a'] = pd.to_datetime(data.year, format = '%Y-%m-%d')
#print(data)
#提取出年月日
#print(data.a.dt.year, data.a.dt.month, data.a.dt.day)

#python中type,dtype,astype的作用与使用要注意,第一个针对单个,第二个针对数组等多个元素
print(type(data.a.dt.year))
print(data.a.dt.year.dtype)

#时间戳转换
timestamp = 1462451334

#转换成localtime
time_local = time.localtime(timestamp)
#转换成新的时间格式(2016-05-05 20:28:54)
dt = time.strftime("%Y-%m-%d %H:%M:%S",time_local)
print (dt)

#pandas里面时间戳转换
data['date']= pd.to_datetime(data['create_time'].values, utc=True, unit='s').tz_convert(
            "Asia/Shanghai").to_period("D")
print(data)


时区转换

#时区划分
#时区名字
#时区是以UTC偏移量的形式表示的
pytz.common_timezones[1:15]
#获取时区对象
tz = pytz.timezone('America/New_York')

#freq就表示时间频率,D代表day,W就代表week,tz就代表时区
rng = pd.date_range('3/9/2012 9:30', periods=6, freq='D')
#rng2已经规定了时区,相当于已经本地化过了
rng2 = pd.date_range('3/9/2012 9:30', periods=6, freq='D', tz='UTC')

#print(rng.tz_localize('Asia/Shanghai'))
#从单纯到本地化的转换是通过tz_localize方法处理的:
ts_utc = rng.tz_localize('UTC')
#print(ts_utc)
#一旦时间序列被本地化到某个特定时区,就可以用tz_convert将其转换到别的时区了:
#print(ts_utc.tz_convert('America/New_York'))

#tz_localize和tz_convert也是DatetimeIndex的实例方法:
ts = pd.Series(np.random.randn(len(rng)), index=rng)
#print(ts.index)
#print(ts.index.tz_localize('Asia/Shanghai'))


#srtftime的使用

正则表达式

#pandas里面的正则###############################################
#1.extract使用  
#如果提取的规则结果有多组,则会返回数据框,不匹配的返回NaN
s3 = pd.Series(['a1', 'b2', 'c3'])
print(s3.str.extract('([ab])(\d)'))
#print(pd.Series(s3).str.extract('([ab])(\d)', expand=False))
print(pd.Series(['a1', 'b2', 'c3']).str.extract('([ab])(\d)', expand=False))


#2.contains使用正则表达式,
#可以将符合的数据进行提取
#print(s3.str.contains('([ab])(\d)'))
#print(s3[s3.str.contains('([ab])(\d)')].unique())

data = {
    'state':['Ohio1','Ohio1','Ohio2','Nevada3','Nevada3'],
    'year':[2000,2001,2002,2001,2002],
    'pop':['1.5','1.7','3.6','2.4','2.9'],
    'salary':['1000K/MTH - 20000K/MTH', '7K/MTH - 8K/MTH',
       '10000K/MTH - 16000K/MTH', '3K/MTH - 5K/MTH', '7K/MTH - 12K/MTH',]
}
frame = pd.DataFrame(data)

#series是将数据形成一个个的列表
#正则记得加括号
#print(pd.Series(data['pop']).str.extract('(\d+\.?\d)'))

#series和dataframe#####################################################################
#注意:extract在dataframe中也适用,不需要再次series,其实series相当于dataframe的一列而已
#所以,诸如head,unique,describe对于dataframe可用的对于series也可用
#print(frame['pop'].str.extract('(\d+\.?\d)'))
#这两个结果就是一样的
#print(pd.Series(data['pop']),'\n', frame['pop'])

#打换行符的时候,需要用引号弄起来哦
data2 = ['1.5','1.7','3.6','2.4','2.9']
#纯数字列表无法用.str方法
#data2 = [1.5,1.7,3.6,2.4,2.9]

#print(data2, '\n' , pd.Series(data2))
data3 = pd.Series(data2)
#print(data3.str.extract('(\d+\.?\d)'))


#re在字符串和pandas中的应用######################################################
#若是字典,那么键值将充当索引
data = {'Dave': '[email protected]', 'Steve': '[email protected]',
        'Rob': '[email protected]', 'Wes': np.nan}


data = pd.Series(data)
#提取,但是.str只针对dataframe或series形式
#print(data.str[:5])

data.isnull()
data.str.contains('gmail')
pattern = '([A-Z0-9._%+-]+)@([A-Z0-9.-]+)\\.([a-z]{2,4})'

#这里用加号和括号就可以把正则提取的东西分别存储在列表中
#print(data.str.extract('([a-z0-9._%+-]+)(@+)([a-z0-9.-]+)\\.([a-z]{2,4})'))

#使用正则表达式,还可以加上任意re选项(如IGNORECASE),这个貌似不看大小写吧好像
#print(data.str.findall(pattern, flags=re.IGNORECASE))

#获取true或false
matches = data.str.match(pattern, flags=re.IGNORECASE)



#例子########################################################
def Find(string): 
    # findall() 查找匹配正则表达式的字符串
    url = re.findall('https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+', string)
    #'https://([\w.])+'也是对的
    return url 
      
 
string = 'Runoob 的网页地址为:https://www.runoob.com,Google 的网页地址为:https://www.google.com'
print("Urls: ", Find(string))
'''

另外一些函数(sum,count,add,fill)

import pandas as pd  

data = {
    'state':['Ohio2','Ohio2','Ohio2','Nevada2','Nevada2'],
    'year':[2002,2012,2022,2012,2022],
    'pop':[1.52,1.72,3.62,2.42,2.92],
    'salary':['5000K/MTH - 20000K/MTH', '12K/MTH - 19K/MTH',
       '4000K/MTH - 6000K/MTH', '14000K/MTH - 22000K/MTH','8000K/MTH - 20000K/MTH']
}
frame = pd.DataFrame(data)
#这个只针对非str的数据相加求总和
print(frame.groupby(data['state']).sum())
#这个则是分组计算数目
print(frame.groupby(data['state']).count())

#使用df1的add方法,传入df2以及一个fill_value参数,就是一个填充值,不然会用NaN代替,他的数学运算是按照索引一一对应!
#print(s1.add(s2,fill_value = 0))
#实例
#当计算结果为NAN时,需要用特定的值来补充代替
import pandas as pd
s1=pd.Series([1,2,3,4],index=['a','b','c','d'])
s2=pd.Series([10,20,30,40],index=['c','d','e','f'])
s3=pd.Series([1,2,3,4],index=['a','b','c','d'])
s4=pd.Series([10,20,30,40],index=['c','d','e','f'])
print (s1+s2) #--1--直接相加只有索引c\d对应有值
print ((s1+s2).dropna())#--2--去除值为空的
print ((s1+s2).fillna(0))#--3--把值为空的地方填充成0
print (s1.add(s2,fill_value=1)) #--4--s1和s2相加,当索引对应值不存在,用1代替s2中元素和s1相加

#针对索引
#pandas可以对不同索引的对象进行算术运算。在将对象相加时,如果存在不同的索引对,则结果的索引就是该索引对的并集。
s1 = pd.Series([7.3, -2.5,'', 1.5], index=['a', 'c', 'd', 'e'])
s2 = pd.Series([-2.1, 3.6, -1.5, 4],index=['a', 'c', 'e', 'f'])
print(s1 + s2)

典型筛选案例

自定义函数

import pandas as pd
import numpy as np
import re

#针对于字符串的替换筛选###########################################
salary = ['8千-1万', '5千-8千', '面议', '1.5万-2万', '1.5万-3万', '1万-1.5万', '7千-1.5万',
       '1.5万-2.5万', '1万-2万', '8千-1.5万', '2.5万以上', '7千-1万', '3千-8千',
       '2千-1万', '5千-1万', '4千-1万', '5千-6千', '3千-5千', '2万-2.5万', '6千-1万']
salary = pd.Series(salary)

def process_k(data):
    if '千' in data:
        return float(data.replace('千', '')) * 1000
    elif '万' in data:
        return float(data.replace('万', '')) * 10000


def process_salary(data):
    if data == '面议':
        return np.nan
    if '万以上' in data:
        return float(data.replace('万以上', '')) * 10000
    if '千以下' in data:
        return float(data.replace('千以下', '')) * 1000
    if '-' in data:
        low, high = data.split('-')
        return (process_k(low) + process_k(high))/2
    
salary_clean = salary.apply(process_salary)
#salary_clean = salary_clean[salary_clean>10000]
print(salary_clean)
#print(salary_clean.unique())

#针对于数字和字符串的清洗筛选############################################
data = {
    'state':['Ohio1','Ohio1','Ohio2','Nevada3','Nevada3'],
    'year':[2000,2001,2002,2001,2002],
    'pop':[1.5,1.7,3.6,2.4,2.9],
    'salary':['1000K/MTH - 20000K/MTH', '7K/MTH - 8K/MTH',
       '10000K/MTH - 16000K/MTH', '3K/MTH - 5K/MTH', '7K/MTH - 12K/MTH']
}
frame = pd.DataFrame(data)


def get_salary_jlc(data):
    pat_jlc = r"(.*)K/MTH - (.*)K/MTH"
    if '00' in data:
        low, high = re.findall(pattern=pat_jlc, string=data)[0]
        return (float(low)+float(high))/2/1000
    else:
        low, high = re.findall(pattern=pat_jlc, string=data)[0]
        return (float(low)+float(high))/2
    
frame['salary_clean'] = frame['salary'].apply(get_salary_jlc)

#print(frame.head())
#print(frame['salary'].iloc[:3])
x = re.findall("(.*)K/MTH - (.*)K/MTH", '1000K/MTH - 20000K/MTH')
#print(x)
low, high = re.findall("(.*)K/MTH - (.*)K/MTH", '1000K/MTH - 20000K/MTH')[0]
#print(low,' ', high)

函数组合

#所有元素的累计和
print(data['a'].astype('int64').sum())
print(data['a'].cumsum())
print(data['a'].astype('int64').sort_values(ascending = False))
'''
#非空元素的数量
print(data['b'].notnull().sum())
#第a列索引为2的元素
print(data.a[2])

#检测和过滤异常值,一般就依靠算法了#####################
#生成4组,每一组包含1000个元素,numpy.random.rand()则相反
data = pd.DataFrame(np.random.randn(1000, 4))
#print(data[2][np.abs(data[2])>3])
#print(data[(np.abs(data) > 3).any(1)])

#字符串对象方法###########################
val = 'a,b,  guido'
val1 = val.split(',')
#strip方法不支持列表操作
pieces = [x.strip() for x in val.split(',')]
print(val1,' ',pieces)
#可以直接赋值
first, second, third = pieces
#下面两种方法一样
first + '::' + second + '::' + third
'::'.join(pieces)

其他(重采样,take,data-dict转换等)

import numpy as np; import pandas as pd


values = pd.Series([0, 1, 0, 2] * 2)
dim = pd.Series(['apple', 'orange','banana'])

#可以使用take方法存储原始的字符串Series:
#用于分类,但是values和dim里面的类别数量必须相等,否则报错
#print(dim.take(values))

#
fruits = ['apple', 'orange', 'apple', 'apple'] * 2

N = len(fruits)
df = pd.DataFrame({'fruit': fruits,
                   'basket_id': np.arange(N),
                   'count': np.random.randint(3, 15, size=N),
                   'weight': np.random.uniform(0, 4, size=N)},
                  columns=['basket_id', 'fruit', 'count', 'weight'])

#dtypes(查询数据类型) 、astype(强制转换数据类型)
fruit_cat = df['fruit'].astype('category')
#print(fruit_cat)

#GroupBy高级应用#################################
df = pd.DataFrame({'key': ['a', 'b', 'c'] * 4,
                   'value': np.arange(12.)})

g = df.groupby(df['key'])
print(g.mean())

#重采样
df = pd.DataFrame({'time': np.arange(N * 3.),
                    'key': np.tile(['a', 'b', 'c'], N),
                    'value': np.arange(N * 3.)})
print(df)
print(df.set_index('key'))


#下面用法自行体会
data = {'col_1': [3, 2, 1, 0], 'col_2': ['a', 'b', 'c', 'd']}
data1 = pd.DataFrame.from_dict(data)
data2 = pd.DataFrame(data)
data3 = pd.DataFrame.from_dict(data, orient='index',
                       columns=['A', 'B', 'C', 'D'])
print(data1)
print(data2)
print(data3)

numpy基础

import numpy as np

my_arr = np.arange(10)
#print((my_arr)[1])
my_list = list(range(10))
#print(my_list[1])

arr = np.arange(8)
#1.数组重塑###################################################
arr2 = arr.reshape(4,2)
#reshape将一维数组转换为多维数组的运算过程相反的运算通常称为扁平化(flattening)或散开(raveling):
arr3 = arr2.ravel()
arr4 = arr2.flatten()
#print(arr3, arr4)

#2.数据的合并和拆分#############################################3
arr1 = np.array([[1, 2, 3], [4, 5, 6]])
arr2 = np.array([[7, 8, 9], [10, 11, 12]])
#按列合并
np.concatenate([arr1, arr2], axis=0)
#按行合并
np.concatenate([arr1, arr2], axis=1)

#对于常见的连接操作,NumPy提供了一些比较方便的方法(如vstack和hstack)
#按列合并
np.vstack((arr1, arr2))
#按行合并 
np.hstack((arr1, arr2))

#与此相反,split用于将一个数组沿指定轴拆分为多个数组:传入到np.split的值[1,3]指示在哪个索引处分割数组。
arr = np.random.randn(5, 2)
first, second, third = np.split(arr, [1,3])

#3.元素的重复操作:tile和repeat######################################
arr = np.arange(3)
arr.repeat(3)
#如果传入的是一组整数,则各元素就可以重复不同的次数:但是个数也必须对应
#同样,在对多维进行重复时,也可以传入一组整数,这样就会使各切片重复不同的次数:
arr.repeat([2, 3, 4])
#对于多维数组,还可以让它们的元素沿指定轴重复:
arr = np.random.randn(2, 2)
arr.repeat(2, axis = 1)
#注意,如果没有设置轴向,则数组会被扁平化,这可能不会是你想要的结果
#print(arr.repeat(2))


#4.索引:################################################
# 获取和设置数组子集的一个办法是通过整数数组使用花式索引:
arr = np.arange(10) * 100
inds = [7, 1, 2, 6]
#两种方法一样
arr[inds]
arr.take(inds)
#在inds索引处的数用42代替
arr.put(inds, 42)

#要在其它轴上使用take,只需传入axis关键字即可:
arr = np.random.randn(2, 4)
print(arr)
#抽取arr按行的每个数据的第1,2个
print(arr.take([0, 1], axis =1))

我写不动了,下次再补。。。

你可能感兴趣的:(Python,python,数据分析,大数据,数据挖掘,visual,studio,code)