利用python进行数据分析学习笔记1(数据清洗和准备)

处理缺失数据

创建一个含缺失值的Series

string_data = pd.Series(['aardvark', 'artichoke', np.nan, 'avocado'])
string_data.isnull()

通过isnull方法返回一个布尔型Series,缺失值显示为True。

利用python进行数据分析学习笔记1(数据清洗和准备)_第1张图片利用python进行数据分析学习笔记1(数据清洗和准备)_第2张图片

通过索引可以将非缺失值设置为缺失值

string_data[0] = None

处理缺失数据的函数

dropna,除去缺失数据

fillna,用指定值填充缺失值

isnull,返回布尔型对象,缺失值显示True,其他显示False

notnull,isnull的否定式


滤除缺失数据

from numpy import nan as NA    #从numpy模块中可以引入缺失值。
data = pd.Series([1,NA,3.5,NA,7])    #创建含缺失值的Series
data.dropna()    #去除Series中的缺失值

利用python进行数据分析学习笔记1(数据清洗和准备)_第3张图片利用python进行数据分析学习笔记1(数据清洗和准备)_第4张图片

data[data.notnull()]    #与data.dropna()等价

利用python进行数据分析学习笔记1(数据清洗和准备)_第5张图片

对DataFrame对象,dropna方法默认丢弃所有含有缺失值的行。

data = pd.DataFrame([[1., 6.5, 3.], [1., NA, NA],
                    [NA, NA, NA], [NA, 6.5, 3.]])
cleaned = data.dropna()

利用python进行数据分析学习笔记1(数据清洗和准备)_第6张图片

传入参数how='all'则只除去整行都是NA的行。

cleaned = data.dropna(how='all')

利用python进行数据分析学习笔记1(数据清洗和准备)_第7张图片

传入参数axis=1或者axis='columns'则会改为逐列删除。

data = pd.DataFrame([[1., NA, 3.], [1., NA, NA],
                    [2, NA, NA], [3, NA, 3.]])
cleaned = data.dropna(axis=1)
cleaned2 = data.dropna(axis=1,how='all')

利用python进行数据分析学习笔记1(数据清洗和准备)_第8张图片利用python进行数据分析学习笔记1(数据清洗和准备)_第9张图片利用python进行数据分析学习笔记1(数据清洗和准备)_第10张图片

dropna的thresh参数,如设置thresh=2,表示如果某行至少有2个非缺失值时将该行保留下来

df = pd.DataFrame(np.random.randn(7,3))    #创建一个7行3列的DataFrame
df.iloc[:4,1] = NA    #将数据框列1的前四行设置为缺失值
df.iloc[:2,2] = NA    #将数据框列2的前两行设置为缺失值

利用python进行数据分析学习笔记1(数据清洗和准备)_第11张图片

df.dropna(thresh=2)   #行数据有两个及以上非缺失值时将保留该行

利用python进行数据分析学习笔记1(数据清洗和准备)_第12张图片

df.dropna(thresh=3)   #行数据有三个及以上非缺失值时将保留该行

利用python进行数据分析学习笔记1(数据清洗和准备)_第13张图片


填充缺失数据

Series和DataFrame都有fillna方法可以填充缺失数据

df.fillna(0)

利用python进行数据分析学习笔记1(数据清洗和准备)_第14张图片利用python进行数据分析学习笔记1(数据清洗和准备)_第15张图片

fillna()方法可以传入字典,实现对不同列的缺失值用不同的值进行填充

df.fillna({1:0.5,2:0})    #列1的缺失值用0.5来填充,列2的缺失值用0来填充

利用python进行数据分析学习笔记1(数据清洗和准备)_第16张图片

若传入inplace=True参数,则可以实现就地修改(慎用)

df.fillna(0,inplace=True)

利用python进行数据分析学习笔记1(数据清洗和准备)_第17张图片

fillna传入method='ffill'参数,缺失值会以上方非缺失值为参数进行填充。

df = pd.DataFrame(np.random.randn(6, 3))
df.iloc[2:, 1] = NA
df.iloc[4:, 2] = NA
df.fillna(method='ffill')

利用python进行数据分析学习笔记1(数据清洗和准备)_第18张图片利用python进行数据分析学习笔记1(数据清洗和准备)_第19张图片

传入limit参数可以限制填充缺失值数量。

df.fillna(method='ffill',limit=2)    #限制一列只能填充两个缺失值

利用python进行数据分析学习笔记1(数据清洗和准备)_第20张图片

可以利用fillna实现许多别的功能,如用平均值来填充缺失值。

data = pd.Series([1,NA,3.5,NA,7])
data.fillna(data.mean())

利用python进行数据分析学习笔记1(数据清洗和准备)_第21张图片利用python进行数据分析学习笔记1(数据清洗和准备)_第22张图片

fillna的参数:value、method、axis、inplace、limit


数据转换

移除重复数据

data = pd.DataFrame({'k1':['one','two'] * 3 + ['two'],'k2':[1,1,2,3,3,4,4]})

创建含重复数据的DataFrame。

利用python进行数据分析学习笔记1(数据清洗和准备)_第23张图片

duplicated()方法返回一个布尔型Series,重复值标记为True。

利用python进行数据分析学习笔记1(数据清洗和准备)_第24张图片

drop_duplicates()方法可以删去重复值。

利用python进行数据分析学习笔记1(数据清洗和准备)_第25张图片

duplicated和drop_duplicates都是默认判断全部列,也可以指定部分列。

data['v1'] = range(7)    #增加一列
data.drop_duplicates(['k1'])    #仅对k1列进行判断

默认情况下保留的是第一个出现的值组合,传入参数keep = 'last'则保留最后一个

利用python进行数据分析学习笔记1(数据清洗和准备)_第26张图片


利用函数或映射进行数据转换

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]})

创建一个DataFrame

利用python进行数据分析学习笔记1(数据清洗和准备)_第27张图片

现在要添加一列表示food列的来源,先编写一个映射。

meat_to_animal = {
  'bacon': 'pig',
  'pulled pork': 'pig',
  'pastrami': 'cow',
  'corned beef': 'cow',
  'honey ham': 'pig',
  'nova lox': 'salmon'
}

food列中有大写有小写,先用str.lower()方法全部变成小写。

lowercased = data['food'].str.lower()

利用python进行数据分析学习笔记1(数据清洗和准备)_第28张图片

在DataFrame中创建一个新列aminal

data['aminal'] = lowercased.map(meat_to_animal)

右边表示将lowercased的每个元素到字典meat_to_animal中找到映射值,返回映射值的Series。

利用python进行数据分析学习笔记1(数据清洗和准备)_第29张图片

将上面的步骤合并简化

data['food'].str.lower().map(meat_to_animal)

利用python进行数据分析学习笔记1(数据清洗和准备)_第30张图片


替换值

data = pd.Series([1,-999,2,-999,-1000,3])    #创建一个Series
data.replace(-999,np.nan)    #将其中的-999用缺失值来替换,非原地修改

利用python进行数据分析学习笔记1(数据清洗和准备)_第31张图片利用python进行数据分析学习笔记1(数据清洗和准备)_第32张图片

被替换值和替换值都可以传入多个,通过列表形式传入。

利用python进行数据分析学习笔记1(数据清洗和准备)_第33张图片

传入的参数可以是字典,键表示被替换值,值表示替换值。

利用python进行数据分析学习笔记1(数据清洗和准备)_第34张图片


重命名轴索引

data = pd.DataFrame(np.arange(12).reshape((3, 4)),
                    index=['Ohio', 'Colorado', 'New York'],
                    columns=['one', 'two', 'three', 'four'])
transform = lambda x:x[:4].upper()
data.index.map(transform)

将data.index中每个元素作为参数传入transform函数中,即取每个元素的前四位并最大值。


可以将返回值赋值给index,对DataFrame的行索引进行就地修改

data.index = data.index.map(transform)

利用python进行数据分析学习笔记1(数据清洗和准备)_第35张图片

通过rename方法可以在原索引的基础上进行修改。

data.rename(index=str.title,columns=str.upper)

此代码表示将行索引每个元素首字母大写化,其余字母小写,列索引所有字母大写化,就地修改。

利用python进行数据分析学习笔记1(数据清洗和准备)_第36张图片

index和columns参数可以传入字典,字典的键是原索引,值是新索引。

data.rename(index={'OHIO': 'INDIANA'},
            columns={'three': 'peekaboo'})

将指定原索引改为新索引,非原地修改。

利用python进行数据分析学习笔记1(数据清洗和准备)_第37张图片

传入inplace参数可以原地修改。

data.rename(index={'OHIO': 'INDIANA'}, inplace=True)

利用python进行数据分析学习笔记1(数据清洗和准备)_第38张图片


离散化和面元划分

现在有一组年龄数据

ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]

要将数据分为18-25,26-35,35-60及60以上的几个面元,通过pandas的cut方法可以实现。

bins = [18,25,35,60,100]    #划分列表
cats = pd.cut(ages,bins)

给出了每个数字所在的区间合起来的列表。

返回的对象有一个codes属性,返回各个元素所在区间的顺序的列表。

如第一个元素20所在区间是18-25,该区间是第一个区间,所以用0表示。


categories属性返回所有区间。


value_counts属性计算各个区间分别有多少个元素。

利用python进行数据分析学习笔记1(数据清洗和准备)_第39张图片

默认情况下区间是左开右闭,可以通过在cut方法中传入参数right=False可以改为左闭右开。

cats = pd.cut(ages, bins,right=False)

cut方法中有个labels参数,传入一个列表,其中的元素可以作为区间的名称。

group_names = ['Youth', 'YoungAdult', 'MiddleAged', 'Senior']
pd.cut(ages,bins,labels=group_names)

可以向cut方法传入需要分隔的区间个数而不是具体边界,程序会自动计算出区间大小。

data = np.random.rand(20)
pd.cut(data,4,precision=2)

将data数组分为4块,precision表示限定小数为两位。

利用python进行数据分析学习笔记1(数据清洗和准备)_第40张图片

利用python进行数据分析学习笔记1(数据清洗和准备)_第41张图片

qcut()方法是分位数切割方法。

data = np.random.randn(1000)
cats = pd.qcut(data,4)

表示将数据分为4块,每块的数据数量都是250个,即四分位。

利用python进行数据分析学习笔记1(数据清洗和准备)_第42张图片

通过pd.value_counts()方法统计各区间的数据数量。

利用python进行数据分析学习笔记1(数据清洗和准备)_第43张图片

可以自定义每块数据的数量,如传入列表[0,0.1,0.5,0.9,1.]作为参数,表示将数据分为四块,第一块占总数量的十分之一,第二块和第三块各占总数量的五分之二,最后一块占总数量的十分之一。

cats = pd.qcut(data, [0, 0.1, 0.5, 0.9, 1.])
pd.value_counts(cats)

利用python进行数据分析学习笔记1(数据清洗和准备)_第44张图片


检测和过滤异常值

data = pd.DataFrame(np.random.randn(1000,4))
data.describe()

创建一个DataFrame,共四列,每列1000个数据,对DataFrame进行描述统计。

 利用python进行数据分析学习笔记1(数据清洗和准备)_第45张图片

利用python进行数据分析学习笔记1(数据清洗和准备)_第46张图片

假如想找出某列中绝对值大小超过3的值

col = data[2]
col[np.abs(col) > 3]

传入一个布尔型数组作为索引。

利用python进行数据分析学习笔记1(数据清洗和准备)_第47张图片

要选出全部含有超过3或-3的值的行,可以在布尔型DataFrame中使用any方法

data[(np.abs(data) > 3).any(1)]

利用python进行数据分析学习笔记1(数据清洗和准备)_第48张图片

返回结果的每行中都有绝对值大于3的值,np.abs(data)>3返回的是布尔型DataFrame,对这个返回结果再执行any(1),表示筛选出行中有绝对值大于3的数值,返回布尔型Series。将这个布尔型Series作为data的索引,取出所有布尔值为True的值。

将值限制在区间-3~3之间

data[np.abs(data) > 3] = np.sign(data) * 3
data.describe()

第一行代码将data数据中绝对值大于3的数据设为3或-3。

利用python进行数据分析学习笔记1(数据清洗和准备)_第49张图片

sign方法根据数据是正、负、零,分别返回+1,-1,0。

np.sign(data).head()

利用python进行数据分析学习笔记1(数据清洗和准备)_第50张图片


排列和随即采样

numpy.random.permutation函数可以实现对Series或DataFrame的列的排列工作,随机重排序。通过需要排列的轴的长度调用permutation,可产生一个表示新顺序的整数数组。

df = pd.DataFrame(np.arange(5 * 4).reshape((5,4)))
sampler = np.random.permutation(5)

利用python进行数据分析学习笔记1(数据清洗和准备)_第51张图片

sampler是将0-4随机排列的数组。

使用take函数对DataFrame的行进行重排序,顺序使用sampler

df.take(sampler)


可以看到行索引的顺序发生了改变。

如果不想用替换的方式选取随机子集,可以用sample方法,非原地修改

df.sample(n=3)

sample(n=3)表示在df中随机取三行。

利用python进行数据分析学习笔记1(数据清洗和准备)_第52张图片

要通过替换的方式产生样本(允许重复选择),传入参数replace=True。

choices = pd.Series([5, 7, -1, 6, 4])
draws = choices.sample(n=10, replace=True)

利用python进行数据分析学习笔记1(数据清洗和准备)_第53张图片

利用python进行数据分析学习笔记1(数据清洗和准备)_第54张图片利用python进行数据分析学习笔记1(数据清洗和准备)_第55张图片


计算指标/哑变量

比如现在有一个三分类的分类变量A、B、C,设两个变量将这三个分类用数字表示,A用0,0表示,B用1,0表示,C用0,1表示。

程序中稍有不同,K个分类,会派生出k列矩阵。

df = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'b'],
                   'data1': range(6)})
pd.get_dummies(df['key'])

利用python进行数据分析学习笔记1(数据清洗和准备)_第56张图片利用python进行数据分析学习笔记1(数据清洗和准备)_第57张图片

a用1,0,0表示,b用0,1,0表示,c用0,0,1表示。

如果想给列索引加一个前缀,可以通过get_dummies方法中的prefix参数实现

dumies = pd.get_dummies(df['key'],prefix='key')
df_with_dummy = df[['data1']].join(dummies)    #选取df中的指定列,和dumies合并

利用python进行数据分析学习笔记1(数据清洗和准备)_第58张图片利用python进行数据分析学习笔记1(数据清洗和准备)_第59张图片

若DataFrame中的某行同属于多个分类会比较复杂

mnames = ['movie_id', 'title', 'genres']
movies = pd.read_table('datasets/movielens/movies.dat', sep='::',
                        header=None, names=mnames)    #读取数据,选择无数据头,用外部列表作为列名
movies[:10]    #取数据的前十行

利用python进行数据分析学习笔记1(数据清洗和准备)_第60张图片

可以看到genres列中有多个电影类型。

将所有类型放到一个list中。

all_genres = []
for x in movies.genres:
    all_genres.extend(x.split('|'))
genres = pd.unique(all_genres)

利用python进行数据分析学习笔记1(数据清洗和准备)_第61张图片

zero_matrix = np.zeros((len(movies),len(genres)))    #创建多行多列的全0数组
dummies = pd.DataFrame(zero_matrix,columns=genres)    #根据数组创建DataFrame,列名是genres中的元素

利用python进行数据分析学习笔记1(数据清洗和准备)_第62张图片

gen = movies.genres[0]    #取出movies的genres列的第一行数据
gen.split('|')    #拆分
dummies.columns.get_indexer(gen.split('|'))    #返回拆分结果在dummies的列名中的排行

for i, gen in enumerate(movies.genres):
    indices = dummies.columns.get_indexer(gen.split('|'))
    dummies.iloc[i, indices] = 1

举个例子,将movies的genres列的第一行的电影类型对应的dummies中的列改为1。

利用python进行数据分析学习笔记1(数据清洗和准备)_第63张图片

例如genres列中第一行的电影类型是Animation、Children's,Comedy,上面的代码就是将dummies中的第一行对应的三列的数值改为1。

通过join方法将movies数据和加前缀的dummies数据合并起来

movies_windic = movies.join(dummies.add_prefix('Genre_'))
movies_windic.iloc[0].head(10)    #取第一行的前十列看看
利用python进行数据分析学习笔记1(数据清洗和准备)_第64张图片

结合get_dummies和诸如cut之类的离散化函数。
np.random.seed(12345)    #设随机种子为12345
values = np.random.rand(10)    #取10个在0-1之间的随机数字
bins = [0,0.2,0.4,0.6,0.8,1]
pd.get_dummies(pd.cut(values,bins))

pd.cut(values,bins)表示按bins的区间给values的值分区间


get_dummies是计算哑变量用的函数。



字符串操作

字符串对象方法

字符串split方法可以根据分隔符拆分字符串,返回列表

val = 'a,b, guido'
val.split(',')

split常与strip一起用,以除去空白符。

pieces = [x.strip() for x in val.split(',')]

用加法将子字符串用::连接起来,这种方法不常用。

first,second,third = pieces
first + '::' + second + '::' + third

更常用的方法是join方法。

'::'.join(pieces)

通过in方法判断某字符串中是否包含某字符。


通过index方法查找指定字符的位置,如果字符不存在会返回异常。


通过find方法查找指定字符位置,如果不存在则返回-1。


replace方法,将指定字符替换成其他字符。


python常用字符串方法

count,返回某字符在字符串中出现的次数。

endswith,startswith,判断字符串是否以某字符开头。

join,将某字符作为连接列表中多个字符串的分隔符

index,在字符串中找某字符的位置。

find同上。

rfind,找某字符在字符串中最后一次出现的位置,没有则返回-1。

replace,替换字符。

strip、rstrip、lstrip,去除空白符,换行符,制表符。

split,将字符串按某字符进行分隔。

lower,upper,将字符串小写化和大写化。

ljust、rjust,设定最低宽度限制,不足的用空格或者其他字符填充。


正则表达式

现有一个字符串,其中每几个字母间有若干个空格,现在要根据若干个字符进行拆分。

import re
text = "foo    bar\t baz  \tqux"
re.split('\s+',text)

\s+表示一个或多个空白符。

可以将匹配规则做成可重用对象。

regex = re.compile('\s+')
regex.split(text)

如果希望得到匹配regex的所有模式,可以使用findall方法


返回所有匹配的结果。

match和search跟findall的功能类似,findall是返回字符串中所有匹配项,search是返回第一个匹配项,match很严格,只匹配字符串的首部。

下面是对邮箱字符串的匹配。

text = """Dave [email protected]
Steve [email protected]
Rob [email protected]
Ryan [email protected]
"""
pattern = r'[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}'    #匹配规则
regex = re.compile(pattern,flags=re.IGNORECASE)    #将匹配规则做成可重用对象,flags参数表示大小不敏感

使用findall将得到所有的邮箱。

regex.findall(text)

search会返回第一个匹配到的邮箱

regex.search(text)

结果只是告诉我们匹配对象在原字符串中起始和结束的位置。

m = regex.search(text)
text[m.start():m.end()]

regex.match将返回None,因为它只匹配出现在字符串开头的模式。

print(regex.match(text))

sub方法可以将匹配到的模式替换为指定字符串,返回得到的新字符串。

print(regex.sub('REDACTED',text))

如果想将匹配到的电子邮件地址分成三部分,用户名,域名和域名后缀,将匹配规则中指定区域用()括起来即可。

pattern = r'([A-Z0-9._%+-]+)@([A-Z0-9.-]+)\.([A-Z]{2,4})'
regex = re.compile(pattern, flags=re.IGNORECASE)
regex.findall(text)

利用python进行数据分析学习笔记1(数据清洗和准备)_第65张图片

m = regex.match('[email protected]')
m.groups()

match方法和search方法返回的结果都能用groups()方法,但findall()方法返回的不行,因为它返回的是一个元组列表。

sub还能通过\1、\2这样的形式访问匹配项的分组。

print(regex.sub(r'Username:\1,Domain:\2,Suffix:\3',text))

利用python进行数据分析学习笔记1(数据清洗和准备)_第66张图片


pandas的矢量化字符串函数

data = {'Dave': '[email protected]', 'Steve': '[email protected]',
        'Rob': '[email protected]', 'Wes': np.nan}    
data = pd.Series(data)    #根据字典创建一个Series
data.isnull()    #使用isnull方法返回一个Series,缺失值显示True,非缺失值显示False

利用python进行数据分析学习笔记1(数据清洗和准备)_第67张图片利用python进行数据分析学习笔记1(数据清洗和准备)_第68张图片

data.str.contains('gmail')

利用python进行数据分析学习笔记1(数据清洗和准备)_第69张图片

通过Series的str.contains方法检查元素是否含有指定字符串。

也可以使用正则表达式

data.str.findall(pattern,flags=re.IGNORECASE)

利用python进行数据分析学习笔记1(数据清洗和准备)_第70张图片

取出data中的每个元素进行匹配,findall方法返回list。

matches = data.str.match(pattern,flags=re.IGNORECASE)

利用python进行数据分析学习笔记1(数据清洗和准备)_第71张图片

使用str.get方法可以获取列表元素。

matches.str.get(1)    #获取列表的第二个元素
matches.str[0]    #获取列表的第一个元素

利用python进行数据分析学习笔记1(数据清洗和准备)_第72张图片利用python进行数据分析学习笔记1(数据清洗和准备)_第73张图片

因为matches中的数据是布尔值,所以取元素都是0缺失值。

因为data的数据是字符串,所以str[:5]选取前五个字符

利用python进行数据分析学习笔记1(数据清洗和准备)_第74张图片

还有更多pandas字符串方法。

利用python进行数据分析学习笔记1(数据清洗和准备)_第75张图片


以上内容主要出自:https://www.jianshu.com/p/ac7bec000dad

你可能感兴趣的:(python)