zoukankan      html  css  js  c++  java
  • 《利用python进行数据分析》读书笔记 --第一、二章 准备与例子

    http://www.cnblogs.com/batteryhp/p/4868348.html

    第一章 准备工作

    今天开始码这本书--《利用python进行数据分析》。R和python都得会用才行,这是码这本书的原因。首先按照书上说的进行安装,google下载了epd_free-7.3-1-win-x86.msi,译者建议按照作者的版本安装,EPDFree包括了Numpy,Scipy,matplotlib,Chaco,IPython.这里的pandas需要自己安装,对应版本为pandas-0.9.0.win32-py2.7.exe.数据下载地址:github.com/pydata/pydata-book.下面是一个文档:

    Welcome to Python For Data Analysis’s documentation!

    http://pda.readthedocs.org/en/latest/

    第二章 引言

    本章是一些例子。

    1、来自bit.ly的1.usa.gov数据

    首先,遇到的问题是pycharm的中文编码问题,注意IDEencoding改为utf-8,同时文件最开始加#-*- encoding:utf-8 -*-,同时含有中文的字符串记得加u。

    下面是代码:

    复制代码
    # -*- encoding: utf-8 -*-
    import json
    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    from collections import defaultdict
    from collections import Counter
    #注意这里的中文路径
    path = u'D:\你好\usagov_bitly_data2012-03-16-1331923249.txt'
    print open(path).readline()
    
    #注意这里的json模块中的loads函数将字符串转换为字典,非常有用!
    #注意这里的缩略循环形式
    records = [json.loads(line) for line in open(path)]
    
    print records[0]
    print type(records)
    print type(records[0])
    print records[0]['tz']
    
    #注意这里的判断条件
    time_zones = [rec['tz'] for rec in records if 'tz' in rec]
    print time_zones[:10]
    
    #下面定义函数对时区进行计数统计,注意这里计数的方式,注意这里的字典初始化方式
    def get_counts(squence):
        counts = defaultdict(int)
        for x in squence:
            counts[x] += 1
        return counts
    
    counts = get_counts(time_zones)
    print counts['America/New_York']
    def top_counts(count_dict,n = 10):
        value_key_pairs = [(count,tz) for tz,count in count_dict.items()]
        value_key_pairs.sort()
        #请注意这里的索引方式,很好
        return value_key_pairs[-n:]
    #这里是打印最后面的十个数,值得注意的是从倒数第十个开始一直到最后一个
    print top_counts(counts)
    #这里的Counter是一个神器,作者真实强大
    counts = Counter(time_zones)
    
    print counts.most_common(10)
    复制代码

    上面是利用python标准库中的函数进行数据分析。需要注意的几个方面:

    1、关于列表索引的说明:

    复制代码
    a = range(0,10,1)
    a[0] >>>0
    a[-1] >>> 9
    a[:5] >>> [0,1,2,3,4]
    a[0:2] >>> [0,1]
    a[-3:-1] >>> [7,8]
    a[-3:] >>> [7,8,9]
    a[-1:-3:-1] >>> [9,8]
    a[::2] >>> [0,2,4,6,8]
    说明:
    1、索引包含第一个,不包含第一个冒号后面的部分
    2、符号表示从后面开始计数
    3、第二个冒号后面是间隔,如果有负号,表示从后面开始计数,例如a[-1:-3]这种表示方式得到空列表。
    复制代码

    2、关于模块 collections 的应用,见下面的地址:

    http://www.zlovezl.cn/articles/collections-in-python/

    collections 主要包括下面几个“数据类型”:namedtuple() 生成可以使用名字来访问元素内容的tuple子类;deque()双端队列,它最大的好处就是实现了从队列 头部快速增加和取出对象;Counter用来统计个数,字典、列表、字符串都能用,很方便;OrderedDict 生成有序字典;defaultdict 也有用 比如 defaultdict(int) 表示字典中每个值都是int型,defaultdict(list)表示字典每个值都是列表。更多更详细的内容见:

    https://docs.python.org/2/library/collections.html#module-collections

    下面是用pandas对时区进行计数

    DataFrame是Pandas最重要的数据结构,应该就是R语言中的数据框。下面看一下实现方式:

    复制代码
    # -*- encoding: utf-8 -*-
    import json
    import numpy as np
    import pandas as pd
    from pandas import DataFrame,Series
    import matplotlib.pyplot as plt
    
    #注意这里的中文路径
    path = u'D:\你好\usagov_bitly_data2012-03-16-1331923249.txt'
    #注意这里的json模块中的loads函数将字符串转换为字典,非常有用!
    #注意这里的缩略循环形式
    records = [json.loads(line) for line in open(path)]
    #注意这里的DataFrame可以将每个元素都是字典的列表自动整理为数据框的形式,每一列是字典的key
    frame = DataFrame(records)
    #数据太多只是会显示缩略图
    #print frame
    #下面是列名为tz的前十个元素
    #print frame['tz'][:10]
    #下面是用value_counts方法对不同的tz计数,太方便了!
    #print type(frame['tz'])
    tz_counts = frame['tz'].value_counts()
    #print tz_counts[:10]
    #下面想画一个茎叶图,首先将缺失值NA进行填充
    clean_tz = frame['tz'].fillna('Missing')
    #下面是对空白符通过布尔型数组索引加以替换
    #值得注意的是,空白符和NA缺失值是不一样的,跟R中道理一样
    clean_tz[clean_tz  == ''] = 'Unknown'
    tz_counts = clean_tz.value_counts()
    print tz_counts[:10]
    #书上说下面这条语句在pylab中打开才管用,其实加一句plt.show()就可以了
    tz_counts[:10].plot(kind = 'barh',rot = 0)
    plt.show()
    复制代码

    下面是对数据中的字符串和表达式之类的进行的工作(前些日子经人指点Beautiful Soup是个爬虫包):

    复制代码
    # -*- encoding: utf-8 -*-
    import json
    import numpy as np
    import pandas as pd
    from pandas import DataFrame,Series
    import matplotlib.pyplot as plt
    from collections import defaultdict
    from collections import Counter
    
    #注意这里的中文路径
    path = u'D:\你好\usagov_bitly_data2012-03-16-1331923249.txt'
    #print open(path).readline()
    #注意这里的json模块中的loads函数将字符串转换为字典,非常有用!
    #注意这里的缩略循环形式
    records = [json.loads(line) for line in open(path)]
    frame = DataFrame(records)
    #对于一个 Series,dropna 返回一个仅含非空数据和索引值的 Series
    results = Series([x.split()[0] for x in frame.a.dropna()])
    #print results.value_counts()
    cframe = frame[frame.a.notnull()]
    #np.where函数是一个矢量化ifelse函数
    operating_system = np.where(cframe['a'].str.contains('Windows'),'Windows','Not Windows')
    #print operating_system[:5]
    #下面是将tz按照operating_system进行分组并计数并用unstack进行展开并填充na为0
    by_tz_os = cframe.groupby(['tz',operating_system])
    agg_counts = by_tz_os.size().unstack().fillna(0)
    #print agg_counts
    #下面注意 sum函数 默认axis = 0,是普通加和,axis = 1是按行加和,argsort是从小到大排序并返回下表
    indexer = agg_counts.sum(1).argsort()
    #下面是取出时区最多的值,注意take函数,接下标
    count_subset = agg_counts.take(indexer)[-10:]
    print count_subset
    #下面的图很好,是累积条形图
    count_subset.plot(kind = 'barh',stacked = True)
    plt.show()
    #下面进行比例展示
    normed_subset = count_subset.div(count_subset.sum(1),axis = 0)
    normed_subset.plot(kind = 'barh',stacked = True)
    plt.show()
    复制代码

    上面一个例子已经完成,看下一个例子。

    GroupLens Research 采集了一组从20世纪90年代末到21世纪初由MovieLens用户提供的电影评分数据。这里的目的在于对数据进行切片分析。

    复制代码
    #-*-coding:utf-8-*-
    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    
    path1 = 'E:\Pyprojects\usepython_2.2\movielens\users.dat'
    path2 = 'E:\Pyprojects\usepython_2.2\movielens\ratings.dat'
    path3 = 'E:\Pyprojects\usepython_2.2\movielens\movies.dat'
    
    unames = ['user_id','gender','age','occupation','zip']
    users = pd.read_table(path1,sep = '::',header = None,names = unames)
    
    rnames = ['user_id','movie_id','rating','timestamp']
    ratings = pd.read_table(path2,sep = '::',header = None,names = rnames)
    
    mnames = ['movie_id','title','genres']
    movies = pd.read_table(path3,sep = '::',header = None,names = mnames)
    
    #print users.head()
    
    #下面是对三个数据集合进行merge操作,最终的行数由ratings决定,原因显然
    data  = pd.merge(pd.merge(ratings,users),movies)
    #print data.ix[0]
    #下面按照性别计算每部电影的平均得分,说实话,这个透视表函数还真是通俗易懂
    mean_ratings = data.pivot_table('rating',rows = 'title',cols = 'gender',aggfunc = 'mean')
    #print mean_ratings.head()
    #下面是按照title对data分组并计数
    ratings_by_title = data.groupby('title').size()
    #下面的index返回的下标
    active_titles = ratings_by_title.index[ratings_by_title >= 251]
    #下面之所以可以这样做是因为groupby函数和透视表都是按照相同是顺序排序的
    mean_ratings = mean_ratings.ix[active_titles]
    #print mean_ratings
    top_female_ratings = mean_ratings.sort_index(by = 'F',ascending = False)
    #print top_female_ratings.head()
    #下面一部分计算男性和女性分歧最大的电影
    #注意,下面的语句直接加入了一列diff,这样得到的就是女性最喜欢的电影,注意方法sort_index的应用
    mean_ratings['diff'] = mean_ratings['M'] - mean_ratings['F']
    sorted_by_diff = mean_ratings.sort_index(by = 'diff')
    #下面是对数据框的行反序并取出前15行,但是 如何对行反序呢?(哦,就是按照原来的行的反向就行)
    #print sorted_by_diff[::-1][:15]
    #下面考虑分歧最大的电影,不考虑性别因素
    rating_std_by_title = data.groupby('title')['rating'].std()
    rating_std_by_title = rating_std_by_title.ix[active_titles]
    #对Series对象进行排序,需要用order
    print rating_std_by_title.order(ascending=False)[:10]
    复制代码

    上面的例子中,有不少需要注意的地方,信息量比较大(对于新手)。下面的例子内容更多一些:

    复制代码
    # -*- encoding: utf-8 -*-
    import json
    import numpy as np
    import pandas as pd
    from pandas import DataFrame,Series
    import matplotlib.pyplot as plt
    from collections import defaultdict
    from collections import Counter
    
    path_base = u'E:\BaiduYun\计算机\python\利用python进行数据分析\pydata-book-masterch02\names\'
    
    #下面读入多个文件到同一个DataFrame中
    years = range(1880,2011)
    pices = []
    columns = ['name','sex','births']
    for year in years:
        path = path_base + 'yob%d.txt' % year
        frame = pd.read_csv(path,names=columns)
    
        frame['year'] = year
        pices.append(frame)
        break
    #注意pd.concat是默认按行进行的合并,是一种outer外连接,按照索引作为连接键
    names = pd.concat(pices,ignore_index=True)
    #下面进行一下聚合,注意这里的pivot_table真是太有用了!
    total_births = names.pivot_table('births',rows = 'year',cols = 'sex',aggfunc=sum)
    #print total_births.tail()
    #total_births.plot(title = 'Total births by sex and year')
    #3plt.show()
    #下面要插入一列,出生量占总出生量的比例
    def add_prop(group):
        #下面将数据换为float类型
        births =group.births.astype(float)
    
        group['prop'] = births / births.sum()
        return group
    names = names.groupby(['year','sex']).apply(add_prop)
    #下面对prop列进行加和看是不是等于1,由于是浮点型数据,用的是allclose函数,判断是否和1足够接近
    #print np.allclose(names.groupby(['year','sex']).prop.sum(),1)
    #现在要取一个子集,是每一个‘year’‘sex’对的出生量前1000名
    
    def get_top1000(group):
        return group.sort_index(by = 'births',ascending=False)[:1000]
    grouped = names.groupby(['year','sex'])
    top1000 = grouped.apply(get_top1000)
    #print top1000.head()
    复制代码

    下面是把后半部分补充完整:

    复制代码
    # -*- encoding: utf-8 -*-
    import os
    import json
    import numpy as np
    import pandas as pd
    from pandas import DataFrame,Series
    import matplotlib.pyplot as plt
    
    path_base = u'D:\pydata-book-master\ch02\names\'
    
    #下面读入多个文件到同一个DataFrame中
    years = range(1880,2011)
    pices = []
    columns = ['name','sex','births']
    for year in years:
        path = path_base + 'yob%d.txt' % year
        frame = pd.read_csv(path,names=columns)
        frame['year'] = year
        pices.append(frame)
    
    #注意pd.concat是默认按行进行的合并,是一种outer外连接,按照索引作为连接键
    names = pd.concat(pices,ignore_index=True)
    #下面进行一下聚合,注意这里的pivot_table真是太有用了!
    
    total_births = names.pivot_table('births',rows = 'year',cols = 'sex',aggfunc=sum)
    #print total_births.tail()
    #total_births.plot(title = 'Total births by sex and year')
    #3plt.show()
    #下面要插入一列,出生量占总出生量的比例
    def add_prop(group):
        #下面将数据换为float类型
        births =group.births.astype(float)
        group['prop'] = births / births.sum()
        return group
    names = names.groupby(['year','sex']).apply(add_prop)
    #下面对prop列进行加和看是不是等于1,由于是浮点型数据,用的是allclose函数,判断是否和1足够接近
    #print np.allclose(names.groupby(['year','sex']).prop.sum(),1)
    #现在要取一个子集,是每一个‘year’‘sex’对的出生量前1000名
    
    def get_top1000(group):
        return group.sort_index(by = 'births',ascending=False)[:1000]
    grouped = names.groupby(['year','sex'])
    top1000 = grouped.apply(get_top1000)
    
    #print top1000.head()
    #下面是分析命名趋势
    boys = top1000[top1000.sex == 'M']
    girls = top1000[top1000.sex == 'F']
    #下面做一个透视表
    total_births = top1000.pivot_table('births',rows = 'year',cols = 'name',aggfunc = sum)
    
    subset = total_births[['John','Harry','Mary','Marilyn']]
    #下面的subplots是用来标明是否将几个图画在一起,figsize用来标明大小,grid 是标明是否有网格线
    #subset.plot(subplots = True,figsize = (12,10),grid = True,title = 'Number of births per year')
    #plt.show()
    
    #下面评估明明多样性的增长,计算最流行的1000个名字所占的比例
    #table = top1000.pivot_table('prop',rows = 'year',cols = 'sex',aggfunc = sum)
    #table.plot(title = 'Sum of table1000.prop by year and sex',yticks = np.linspace(0,1.2,13),xticks = range(1880,2020,10))
    #plt.show()
    #另一个方式是计算总出生人数前50%的不同名字的数量
    #df = boys[boys.year == 2010]
    #下面就要找到prop的和是0.5的位置,书上说写循环也行,但是numpy中也有cunsum函数,R语言中也有,这当然是极好的。
    
    #prop_cumsum = df.sort_index(by = 'prop',ascending = False).prop.cumsum()
    #print prop_cumsum[:10]
    #下面这个函数简直太方便,searchsorted
    #print prop_cumsum.searchsorted(0.5)
    #注意下面的函数,将所有的年份都进行一次计算
    def get_quantile_count(group,q = 0.5):
        group = group.sort_index(by = 'prop',ascending= False)
        return group.prop.cumsum().searchsorted(q) + 1
    
    diversity = top1000.groupby(['year','sex']).apply(get_quantile_count)
    diversity = diversity.unstack('sex')
    #print diversity.head()
    diversity.plot(title = 'Number of popular names in top 50%')
    plt.show()
    
    
    #最后一个字母的变革
    #从name列取出最后一个字母,注意lamda这个语句使用来创建匿名函数
    get_last_letter = lambda x:x[-1]
    #注意这里的map函数是一种 “并行”式的函数,对name的每个元素进行后面的函数
    last_letters = names.name.map(get_last_letter)
    last_letters.name = 'last_letter'
    #下面的语句让我感到了奇怪,为何last_latters不在names中却还能顺利生成数据透视表?毁三观呐
    table = names.pivot_table('births',rows = last_letters,cols = ['sex','year'],aggfunc = sum)
    
    subtable = table.reindex(columns = [1910,1960,2010],level = 'year')
    #print subtable.head()
    letter_prop = subtable / subtable.sum().astype(float)
    fig,axes = plt.subplots(2,1,figsize=(10,8))
    letter_prop['M'].plot(kind = 'bar',rot = 0,ax = axes[0],title = 'Male')
    letter_prop['F'].plot(kind = 'bar',rot = 0,ax = axes[1],title = 'Female',legend = False)
    plt.show()
    
    letter_prop = table / table.sum().astype(float)
    dny_ts = letter_prop.ix[['d','n','y'],'M'].T
    dny_ts.plot()
    plt.show()
    
    #下面是最后一项,变成女孩名字的男孩名字(以及相反的情况)
    all_names = top1000.name.unique()
    #这里的in函数应该是一个部分匹配函数,另外上面的语句中的unique很熟悉,R语言中也有
    mask = np.array(['lesl' in x.lower() for x in all_names])
    lesley_like = all_names[mask]
    #然后用这个结果过滤掉其他的名字,并按名字分组计算出生数以查看相对频率
    #下面这个isin函数非常方便
    flitered = top1000[top1000.name.isin(lesley_like)]
    flitered.groupby('name').births.sum()
    table = flitered.pivot_table('births',rows = 'year',cols = 'sex',aggfunc = 'sum')
    #print table.head()
    #注意这里的div函数是做一个归一化
    table = table.div(table.sum(1),axis = 0)
    print table.head()
    #print table.tail()
    table.plot(style = {'M':'k-','F':'k--'})
    plt.show()
    复制代码

    这二章完事,下一章是IPython,第三章少写一点,本章是受益匪浅

  • 相关阅读:
    hibernate关联关系映射
    java单例模式
    HTML如何给table添加滚动条
    jquery的几种ajax方式对比
    JQuery Selectors 方法说明
    jQuery遍历对象/数组/集合
    Jquery常用函数
    【刷题】【省选】ZJOI2017_仙人掌_LOJ2250/Luogu3687_圆方树/dp计数/树形dp
    【学习笔记】圆方树学习笔记
    【模板】【刷题】差分与前缀和_LuoguP5488_多项式
  • 原文地址:https://www.cnblogs.com/virusolf/p/6168647.html
Copyright © 2011-2022 走看看