大数据与云计算学习:数据分析(一)

图片描述

图片描述

python基础

先看看 基础

注意点

切割操作

图片描述

这里发现我们在取出list中的元素时候是左开右闭的,即[3,6) 索引6对应的元素7并没有被输出
图片描述

改变list中的元素

图片描述

添加删除元素

图片描述

两种拷贝list的方式

list2拷贝给y,y改变,list2也变
图片描述

list2拷贝给y,y改变,list2不变
图片描述

删除实例的属性和删除字典属性的区别

a = {'a':1,'b':2}
del a['a']
a = classname()
del classname.attrname

with as

https://www.cnblogs.com/DswCn...

if name == '__main__':

if __name__ == '__main__':

一个python的文件有两种使用的方法,
第一是直接作为脚本执行,
第二是import到其他的python脚本中被调用(模块重用)执行。
因此if name == 'main':
的作用就是控制这两种情况执行代码的过程,
在if name == 'main': 下的代码只有在第一种情况下(即文件作为脚本直接执行)才会被执行,
而import到其他脚本中是不会被执行的。...

图片描述

函数 /方法

正则表达式

基础看这里

import re
line = 'jwxddxsw33'
if line == "jxdxsw33":
    print("yep")
else:
    print("no")

# ^ 限定以什么开头
regex_str = "^j.*"
if re.match(regex_str, line):
    print("yes")
#$限定以什么结尾
regex_str1 = "^j.*3$"
if re.match(regex_str, line):
    print("yes")

regex_str1 = "^j.3$"
if re.match(regex_str, line):
    print("yes")
# 贪婪匹配
regex_str2 = ".*(d.*w).*"
match_obj = re.match(regex_str2, line)
if match_obj:
    print(match_obj.group(1))
# 非贪婪匹配
# ?处表示遇到第一个d 就匹配
regex_str3 = ".*?(d.*w).*"
match_obj = re.match(regex_str3, line)
if match_obj:
    print(match_obj.group(1))
# * 表示>=0次  + 表示 >=0次
# ? 表示非贪婪模式
# + 的作用至少>出现一次  所以.+任意字符这个字符至少出现一次
line1 = 'jxxxxxxdxsssssswwwwjjjww123'
regex_str3 = ".*(w.+w).*"
match_obj = re.match(regex_str3, line1)
if match_obj:
    print(match_obj.group(1))
# {2}限定前面的字符出现次数 {2,}2次以上 {2,5}最小两次最多5次
line2 = 'jxxxxxxdxsssssswwaawwjjjww123'
regex_str3 = ".*(w.{3}w).*"
match_obj = re.match(regex_str3, line2)
if match_obj:
    print(match_obj.group(1))

line2 = 'jxxxxxxdxsssssswwaawwjjjww123'
regex_str3 = ".*(w.{2}w).*"
match_obj = re.match(regex_str3, line2)
if match_obj:
    print(match_obj.group(1))

line2 = 'jxxxxxxdxsssssswbwaawwjjjww123'
regex_str3 = ".*(w.{5,}w).*"
match_obj = re.match(regex_str3, line2)
if match_obj:
    print(match_obj.group(1))

# | 或

line3 = 'jx123'
regex_str4 = "((jx|jxjx)123)"
match_obj = re.match(regex_str4, line3)
if match_obj:
    print(match_obj.group(1))
    print(match_obj.group(2))
# [] 表示中括号内任意一个
line4 = 'ixdxsw123'
regex_str4 = "([hijk]xdxsw123)"
match_obj = re.match(regex_str4, line4)
if match_obj:
    print(match_obj.group(1))
# [0,9]{9} 0到9任意一个 出现9次(9位数)
line5 = '15955224326'
regex_str5 = "(1[234567][0-9]{9})"
match_obj = re.match(regex_str5, line5)
if match_obj:
    print(match_obj.group(1))
# [^1]{9}
line6 = '15955224326'
regex_str6 = "(1[234567][^1]{9})"
match_obj = re.match(regex_str6, line6)
if match_obj:
    print(match_obj.group(1))

# [.*]{9} 中括号中的.和*就代表.*本身
line7 = '1.*59224326'
regex_str7 = "(1[.*][^1]{9})"
match_obj = re.match(regex_str7, line7)
if match_obj:
    print(match_obj.group(1))

#\s 空格
line8 = '你 好'
regex_str8 = "(你\s好)"
match_obj = re.match(regex_str8, line8)
if match_obj:
    print(match_obj.group(1))

# \S 只要不是空格都可以(非空格)
line9 = '你真好'
regex_str9 = "(你\S好)"
match_obj = re.match(regex_str9, line9)
if match_obj:
    print(match_obj.group(1))

# \w  任意字符 和.不同的是 它表示[A-Za-z0-9_]
line9 = '你adsfs好'
regex_str9 = "(你\w\w\w\w\w好)"
match_obj = re.match(regex_str9, line9)
if match_obj:
    print(match_obj.group(1))

line10 = '你adsf_好'
regex_str10 = "(你\w\w\w\w\w好)"
match_obj = re.match(regex_str10, line10)
if match_obj:
    print(match_obj.group(1))
#\W大写的是非[A-Za-z0-9_]
line11 = '你 好'
regex_str11 = "(你\W好)"
match_obj = re.match(regex_str11, line11)
if match_obj:
    print(match_obj.group(1))

# unicode编码 [\u4E00-\u\9FA5] 表示汉字
line12= "镜心的小树屋"
regex_str12= "([\u4E00-\u9FA5]+)"
match_obj = re.match(regex_str12,line12)
if match_obj:
    print(match_obj.group(1))

print("-----贪婪匹配情况----")
line13 = 'reading in 镜心的小树屋'
regex_str13 = ".*([\u4E00-\u9FA5]+树屋)"
match_obj = re.match(regex_str13, line13)
if match_obj:
    print(match_obj.group(1))

print("----取消贪婪匹配情况----")
line13 = 'reading in 镜心的小树屋'
regex_str13 = ".*?([\u4E00-\u9FA5]+树屋)"
match_obj = re.match(regex_str13, line13)
if match_obj:
    print(match_obj.group(1))

#\d数字
line14 = 'XXX出生于2011年'
regex_str14 = ".*(\d{4})年"
match_obj = re.match(regex_str14, line14)
if match_obj:
    print(match_obj.group(1))

regex_str15 = ".*?(\d+)年"
match_obj = re.match(regex_str15, line14)
if match_obj:
    print(match_obj.group(1))
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

###
# 试写一个验证Email地址的正则表达式。版本一应该可以验证出类似的Email:
#someone@gmail.com
#bill.gates@microsoft.com
###

import re
addr = 'someone@gmail.com'
addr2 = 'bill.gates@microsoft.com'
def is_valid_email(addr):
    if re.match(r'[a-zA-Z_\.]*@[a-aA-Z.]*',addr):
        return True
    else:
        return False

print(is_valid_email(addr))
print(is_valid_email(addr2))

# 版本二可以提取出带名字的Email地址:
# <Tom Paris> tom@voyager.org => Tom Paris
# bob@example.com => bob

addr3 = '<Tom Paris> tom@voyager.org'
addr4 = 'bob@example.com'

def name_of_email(addr):
    r=re.compile(r'^(<?)([\w\s]*)(>?)([\w\s]*)@([\w.]*)$')
    if not r.match(addr):
        return None
    else:
        m = r.match(addr)
        return m.group(2)

print(name_of_email(addr3))
print(name_of_email(addr4))

案例

找出一个文本中词频最高的单词
text = 'the clown ran after the car and the car ran into the tent and the tent fell down on the clown and the car'
words = text.split()
print(words)

for word in words:# 初始化空列表
    print(word)


#步骤一:获得单词列表  相当于去重
unique_words = list()
for word in words:
   if(word not in unique_words):# 使用in判断某个元素是否在列表里
       unique_words.append(word)
print(unique_words)


#步骤二:初始化词频列表

# [e]*n 快速初始化
counts = [0] * len(unique_words)
print(counts)

# 步骤三:统计词频
for word in words:
    index = unique_words.index(word)

    counts[index] = counts[index] + 1
    print(counts[index])
print(counts)
# 步骤四:找出最高词频和其对应的单词
bigcount = None #None 为空,初始化bigcount
bigword = None

for i in range(len(counts)):
    if bigcount is None or counts[i] > bigcount:
        bigword = unique_words[i]
        bigcount = counts[i]
print(bigword,bigcount)

用字典的方式:

# 案例回顾:找出一个文本中最高词频的单词

text = '''the clown ran after the car and the car ran into the tent 
        and the tent fell down on the clown and the car'''
words = text.split() # 获取单词的列表

# 使用字典可以极大简化步骤
# 获取单词-词频字典
counts = dict() # 初始化一个空字典
for word in words:
    counts[word] = counts.get(word, 0) + 1  # 构造字典。注意get方法需要设定默认返回值0(当单词第一次出现时,词频为1)
print(counts)

# 在字典中查找最高词频的单词
bigcount = None
bigword = None
for word,count in counts.items():
    if bigcount is None or count > bigcount:
        bigword = word
        bigcount = count

print(bigword, bigcount)
自定义一个每周工资计算器函数
# 使用input()函数,从键盘读取输入的文本
# a = input('请输入文本:')
# print('您输入的内容是:',a)

def salary_calculator(): #没有参数的函数
    user = str #初始化user为字符串变量
    print("----工资计算器----")

    while True:
        user = input("\n请输入你的名字,或者输入0来结束报告: ")

        if user == "0":
            print("结束报告")
            break
        else:
            hours = float(input("请输入你的工作小时数:"))
            payrate =float(input("请输入你的单位时间工资: ¥"))

            if hours <= 40:
                print("员工姓名:",user)
                print("加班小时数:0")
                print("加班费:¥0.00")
                regularpay = round(hours * payrate,2) # round函数保留小数点后两位
                print("税前工资:¥" + str(regularpay))


            elif hours > 40:

                overtimehours = round(hours - 40, 2)

                print("员工姓名: " + user)

                print("加班小时数: " + str(overtimehours))

                regularpay = round(40 * payrate, 2)

                overtimerate = round(payrate * 1.5, 2)

                overtimepay = round(overtimehours * overtimerate)

                grosspay = round(regularpay + overtimepay, 2)

                print("常规工资: ¥" + str(regularpay))

                print("加班费: ¥" + str(overtimepay))

                print("税前工资: ¥" + str(grosspay))

#调用 salary_calculator

salary_calculator()

这个实例中注意 python中关于round函数的小坑

数据结构、函数、条件和循环

包管理

戳这里看有哪些流行python包——>awesom-python

  • Numpy 处理数组/数据计算扩展

    • ndarray 一种多维数组对象
    • 利用数组进行数据处理
    • 用于数组的文件输入输出
    • 多维操作
    • 线性代数
    • 随机数生成
    • 随机漫步
    • Numpy高级应用

      • ndarray 对象的内部机制
      • 高级数组操作
      • 广播
      • ufunc高级应用
      • 结构化和记录式数组
      • 更多有关排序
      • NumPy的matrix类
      • 高级数组输入输出
  • Matplotlib 数据可视化
  • Pandas 数据分析

    • pandas的数据结构
    • 基本功能
    • 汇总和计算描述统计
    • 处理缺失数据
    • 层次化索引
    • 聚合与分组
    • 逻辑回归基本原理
  • jupyter
pip3 install jupyter
jupyter notebook
  • scipy

  • Scikit-learn 数据挖掘、机器学习
  • keras 人工神经网络
  • tensorflow 神经网络

安装Python包管理工具pip,主要是用于安装 PyPI 上的软件包

安装教程

sudo apt-get install python3-pip
pip3 install numpy
pip3 install scipy
pip3 install matplotlib

或者下这个安装脚本 get-pip.py

图片描述
图片描述
图片描述

包的引入方式

图片描述
因为python是面向对象的编程,推荐引入方式还是

import numpy
numpy.array([1,2,3])

数据存储

数据操作

生成数据

生成一组二维数组,有5000个元素,每个元素内表示 身高和体重
import numpy as np

图片描述

生成1000个经纬度位置,靠近(117,32),并输出位csv
import pandas as pd
import numpy as np

# 任意的多组列表
lng = np.random.normal(117,0.20,1000)

lat = np.random.normal(32.00,0.20,1000)

# 字典中的key值即为csv中列名
dataframe = pd.DataFrame({'lng':lng,'lat':lat})


#将DataFrame存储为csv,index表示是否显示行名,default=True
dataframe.to_csv('data/lng-lat.csv',index = False, sep=',' )

图片描述

numpy的常用操作

#encoding=utf-8 
import numpy as np 
def main():
    lst = [[1,3,5],[2,4,6]]
    print(type(lst))
    np_lst = np.array(lst)
    print(type(np_lst))
    # 同一种numpy.array中只能有一种数据类型
    # 定义np的数据类型
    # 数据类型有:bool int int8 int16 int32 int64 int128 uint8 uint16 uint32 uint64 uint128 float16/32/64 complex64/128
    np_lst = np.array(lst,dtype=np.float)

    print(np_lst.shape)
    print(np_lst.ndim)#数据的维度
    print(np_lst.dtype)#数据类型
    print(np_lst.itemsize) #每个元素的大小
    print(np_lst.size)#数据大小 几个元素

    # numpy array
    print(np.zeros([2,4]))# 生成2行4列都是0的数组
    print(np.ones([3,5]))

    print("---------随机数Rand-------") 
    print(np.random.rand(2,4))# rand用于产生0~1之间的随机数 2*4的数组
    print(np.random.rand())
    print("---------随机数RandInt-------")
    print(np.random.randint(1,10)) # 1~10之间的随机整数
    print(np.random.randint(1,10,3))# 3个1~10之间的随机整数
    print("---------随机数Randn 标准正太分布-------")
    print(np.random.randn(2,4)) # 2行4列的标准正太分布的随机整数
    print("---------随机数Choice-------")
    print(np.random.choice([10,20,30]))# 指定在10 20 30 里面选一个随机数生成
    print("---------分布Distribute-------")
    print(np.random.beta(1,10,100))# 生成beta分布
if __name__ == "__main__":
    main()

图片描述

常用函数举例

计算红酒数据每一个属性的平均值(即每一列数据的平均值)

数据分析工具

数据可视化

图片描述

  • 探索数据
  • 数据展示
  • 数据 ---> 故事
  • matplotlib 绘图基础

    • 函数曲线的绘制
    • 图形细节的设置
  • 案例分析:销售记录可视化

    • 条形图
    • 绘制多图
    • 饼图
    • 散点图
    • 直方图
    • seaborn 数据可视化包

      • 分类数据的散点图
      • 分类数据的箱线图
      • 多变量图

更多内容戳这里 数据可视化

安装 matplotlib

图片描述
图片描述

注意这里会报这样的错误

ImportError: No module named '_tkinter', please install the python3-tk package

需要安装 python3-tk
图片描述

更多示例

线图

图片描述
图片描述
图片描述
图片描述

散点图 & 柱状图

图片描述
图片描述
图片描述
图片描述

数据分析

padans

  • 上层数据操作
  • dataframe数据结构

图片描述

 import pandas as pd
brics = pd.read_csv('/home/wyc/study/python_lession/python_lessions/数据分析/brics.csv',index_col = 0)

图片描述
图片描述

pandas基本操作



import numpy as np
import pandas as pd

def main():

    #Data Structure
    s = pd.Series([i*2 for i in range(1,11)])
    print(type(s))

    dates = pd.date_range("20170301",periods=8)
    df = pd.DataFrame(np.random.randn(8,5),index=dates,columns=list("ABCDE"))
    print(df)
    # basic

    print(df.head(3))
    print(df.tail(3))
    print(df.index)
    print(df.values)
    print(df.T)
    # print(df.sort(columns="C"))
    print(df.sort_index(axis=1,ascending=False))
    print(df.describe())

    #select
    print(type(df["A"]))
    print(df[:3])
    print(df["20170301":"20170304"])
    print(df.loc[dates[0]])
    print(df.loc["20170301":"20170304",["B","D"]])
    print(df.at[dates[0],"C"])


    print(df.iloc[1:3,2:4])
    print(df.iloc[1,4])
    print(df.iat[1,4])

    print(df[df.B>0][df.A<0])
    print(df[df>0])
    print(df[df["E"].isin([1,2])])

    # Set
    s1 = pd.Series(list(range(10,18)),index = pd.date_range("20170301",periods=8))
    df["F"]= s1
    print(df)
    df.at[dates[0],"A"] = 0
    print(df)
    df.iat[1,1] = 1
    df.loc[:,"D"] = np.array([4]*len(df))
    print(df)

    df2 = df.copy()
    df2[df2>0] = -df2
    print(df2)

    # Missing Value
    df1 = df.reindex(index=dates[:4],columns = list("ABCD") + ["G"])
    df1.loc[dates[0]:dates[1],"G"]=1
    print(df1)
    print(df1.dropna())
    print(df1.fillna(value=1))

    # Statistic
    print(df.mean())
    print(df.var())

    s = pd.Series([1,2,4,np.nan,5,7,9,10],index=dates)
    print(s)
    print(s.shift(2))
    print(s.diff())
    print(s.value_counts())
    print(df.apply(np.cumsum))
    print(df.apply(lambda x:x.max()-x.min()))

    #Concat
    pieces = [df[:3],df[-3:]]
    print(pd.concat(pieces))

    left = pd.DataFrame({"key":["x","y"],"value":[1,2]})
    right = pd.DataFrame({"key":["x","z"],"value":[3,4]})
    print('LEFT',left)
    print('RIGHT', right)
    print(pd.merge(left,right,on="key",how="outer"))
    df3 = pd.DataFrame({"A": ["a","b","c","b"],"B":list(range(4))})
    print(df3.groupby("A").sum())



if __name__ == "__main__":
    main()

# 首先产生一个叫gdp的字典
gdp = {"country":["United States", "China", "Japan", "Germany", "United Kingdom"],
       "capital":["Washington, D.C.", "Beijing", "Tokyo", "Berlin", "London"],
       "population":[323, 1389, 127, 83, 66],
       "gdp":[19.42, 11.8, 4.84, 3.42, 2.5],
       "continent":["North America", "Asia", "Asia", "Europe", "Europe"]}

import pandas as pd
gdp_df = pd.DataFrame(gdp)
print(gdp_df)

# 我们可以通过index选项添加自定义的行标签(label)
# 使用column选项可以选择列的顺序
gdp_df = pd.DataFrame(gdp, columns = ["country", "capital", "population", "gdp", "continent"],index = ["us", "cn", "jp", "de", "uk"])
print(gdp_df)

#修改行和列的标签
# 也可以使用index和columns直接修改
gdp_df.index=["US", "CN", "JP", "DE", "UK"]
gdp_df.columns = ["Country", "Capital", "Population", "GDP", "Continent"]
print(gdp_df)
# 增加rank列,表示他们的GDP处在前5位
gdp_df["rank"] = "Top5 GDP"
# 增加国土面积变量,以百万公里计(数据来源:http://data.worldbank.org/)
gdp_df["Area"] = [9.15, 9.38, 0.37, 0.35, 0.24]
print(gdp_df)


# 一个最简单的series
series = pd.Series([2,4,5,7,3],index = ['a','b','c','d','e'])
print(series)
# 当我们使用点操作符来查看一个变量时,返回的是一个pandas series
# 在后续的布尔筛选中使用点方法可以简化代码
# US,...,UK是索引
print(gdp_df.GDP)


# 可以直接查看索引index
print(gdp_df.GDP.index)
# 类型是pandas.core.series.Series
print(type(gdp_df.GDP))

#返回一个布尔型的series,在后面讲到的DataFrame的布尔索引中会大量使用
print(gdp_df.GDP > 4)

# 我们也可以将series视为一个长度固定且有顺序的字典,一些用于字典的函数也可以用于series
gdp_dict = {"US": 19.42, "CN": 11.80, "JP": 4.84, "DE": 3.42, "UK": 2.5}
gdp_series = pd.Series(gdp_dict)
print(gdp_series)

# 判断 ’US' 标签是否在gdp_series中

print("US" in gdp_series)
# 使用变量名加[[]]选取列
print(gdp_df[["Country"]])
# 可以同时选取多列
print(gdp_df[["Country", "GDP"]])


# 如果只是用[]则产生series
print(type(gdp_df["Country"]))
# 行选取和2d数组类似
# 如果使用[]选取行,切片方法唯一的选项
print(gdp_df[2:5]) #终索引是不被包括的!

#loc方法
# 在上面例子中,我们使用行索引选取行,能不能使用行标签实现选取呢?
# loc方法正是基于标签选取数据的方法
print(gdp_df.loc[["JP","DE"]])
# 以上例子选取了所有的列
# 我们可以加入需要的列标签
print(gdp_df.loc[["JP","DE"],["Country","GDP","Continent"]])

# 选取所有的行,我们可以使用:来表示选取所有的行
print(gdp_df.loc[:,["Country","GDP","Continent"]])

# 等价于gdp_df.loc[["JP","DE"]]
print(gdp_df.iloc[[2,3]])

print(gdp_df.loc[["JP","DE"],["Country", "GDP", "Continent"]])
print(gdp_df.iloc[[2,3],[0,3,4]])

# 选出亚洲国家,下面两行命令产生一样的结果
print(gdp_df[gdp_df.Continent == "Asia"])

print(gdp_df.loc[gdp_df.Continent == "Asia"])
# 选出gdp大于3兆亿美元的欧洲国家
print(gdp_df[(gdp_df.Continent == "Europe") & (gdp_df.GDP > 3)])

缺失值处理

数据挖掘

案例:Iris鸢尾花数据集
让我们来看一下经典的iris数据:

  • 鸢尾花卉数据集, 来源 UCI 机器学习数据集
  • 它最初是埃德加·安德森采集的
  • 四个特征被用作样本的定量分析,它们分别是花萼(sepal)和花瓣(petal)的长度(length)和宽度(width)

图片描述

#####
#数据的导入和观察
#####
import pandas as pd
# 用列表存储列标签
col_names = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'species']
# 读取数据,并指定每一列的标签
iris = pd.read_csv('data/iris.txt', names = col_names)

# 使用head/tail查看数据的头和尾

print(iris.head(10))

# 使用info 方法查看数据的总体信息
iris.info()

# 使用shape可以查看DataFrame的行数与列数
# iris有150个观察值,5个变量
print(iris.shape)
# 这里的品种(species)是分类变量(categorical variable)
# 可以使用unique方法来对查看series中品种的名字
print(iris.species.unique())


# 统计不同品种的数量
# 使用DataFrame的value_counts方法来实现
print(iris.species.value_counts())

#选取花瓣数据,即 petal_length 和 petal_width 这两列
# 方法一:使用[[ ]]
petal = iris[['petal_length','petal_width']]
print(petal.head())
# 方法二:使用 .loc[ ]
petal = iris.loc[:,['petal_length','petal_width']]
print(petal.head())
# 方法三:使用 .iloc[ ]
petal = iris.iloc[:,2:4]
print(petal.head())

# 选取行索引为5-10的数据行
# 方法一:使用[]
print(iris[5:11])
# 方法二:使用 .iloc[]
print(iris.iloc[5:11,:])

# 选取品种为 Iris-versicolor 的数据
versicolor = iris[iris.species == 'Iris-versicolor']
print(versicolor.head())


####
#数据的可视化
####
#散点图
import matplotlib.pyplot as plt
# 我们首先画散点图(sactter plot),x轴上画出花瓣的长度,y轴上画出花瓣的宽度
# 我们观察到什么呢?
iris.plot(kind = 'scatter', x="petal_length", y="petal_width")
# plt.show()

# 使用布尔索引的方法分别获取三个品种的数据
setosa = iris[iris.species == 'Iris-setosa']
versicolor = iris[iris.species == 'Iris-versicolor']
virginica = iris[iris.species == 'Iris-virginica']

ax = setosa.plot(kind='scatter', x="petal_length", y="petal_width", color='Red', label='setosa', figsize=(10,6))
versicolor.plot(kind='scatter', x="petal_length", y="petal_width", color='Green', ax=ax, label='versicolor')
virginica.plot(kind='scatter', x="petal_length", y="petal_width", color='Orange', ax=ax, label='virginica')
plt.show()

#箱图
#使用mean()方法获取花瓣宽度均值
print(iris.petal_width.mean())
#使用median()方法获取花瓣宽度的中位数
print(iris.petal_width.median())
# 可以使用describe方法来总结数值变量
print(iris.describe())


# 绘制花瓣宽度的箱图
# 箱图展示了数据中的中位数,四分位数,最大值,最小值
iris.petal_width.plot(kind='box')
# plt.show()

# 按品种分类,分别绘制不同品种花瓣宽度的箱图
iris[['petal_width','species']].boxplot(grid=False,by='species',figsize=(10,6))
# plt.show()

setosa.describe()

# 计算每个品种鸢尾花各个属性(花萼、花瓣的长度和宽度)的最小值、平均值又是分别是多少? (提示:使用min、mean 方法。)
print(iris.groupby(['species']).agg(['min','mean']))

#计算鸢尾花每个品种的花萼长度(sepal_length) 大于6cm的数据个数。
# 方法1
print(iris[iris['sepal_length']> 6].groupby('species').size())
# 方法2
def more_len(group,length=6):
    return len(group[group['sepal_length'] > length])
print(iris.groupby(['species']).apply(more_len,6))

图片描述
图片描述
图片描述
图片描述

缺失值处理 、数据透视表

  • 缺失值处理:pandas中的fillna()方法

    • pandas用nan(not a number)表示缺失数据,处理缺失数据有以下几种方法:

      • dropna去除nan数据
      • fillna使用默认值填入
      • isnull 返回一个含有布尔值的对象,表示哪些是nan,哪些不是
      • notnull isnull的否定式
  • 数据透视表:pandas中的pivot_table函数

我们用案例分析 - 泰坦尼克数据 来说明这个两个问题
缺失值处理:

  • 真实数据往往某些变量会有缺失值。
  • 这里,cabin有超过70%以上的缺失值,我们可以考虑直接丢掉这个变量。 -- 删除某一列数据
  • 像Age这样的重要变量,有20%左右的缺失值,我们可以考虑用中位值来填补。-- 填补缺失值
  • 我们一般不提倡去掉带有缺失值的行,因为其他非缺失的变量可能提供有用的信息。-- 删除带缺失值的行
# 读取常用的包
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

#读取数据
titanic_df = pd.read_csv('data/titanic.csv')

#查看前五行数据
print(titanic_df.head())

# 数据的统计描述
# describe函数查看部分变量的分布
# 因为Survived是0-1变量,所以均值就是幸存人数的百分比,这个用法非常有用
print(titanic_df[["Survived","Age","SibSp","Parch"]].describe())

# 使用include=[np.object]来查看分类变量
# count: 非缺失值的个数
# unique: 非重复值得个数
# top: 最高频值
# freq: 最高频值出现次数

print(titanic_df.describe(include=[np.object]))

#不同舱位的分布情况是怎样的呢?
# 方法1: value_counts
# 查看不同舱位的分布
# 头等舱:24%; 二等舱:21%; 三等舱:55%
# value_counts 频数统计, len() 获取数据长度
print(titanic_df.Pclass.value_counts() / len(titanic_df))
# 总共有891个乘客
# Age有714个非缺失值,Cabin只有204个非缺失值。我们将会讲解如何处理缺失值
print(titanic_df.info())

#方法2:group_by
# sort_values 将结果排序
(titanic_df.groupby("Pclass").agg("size")/len(titanic_df)).sort_values(ascending=False)

# 填补年龄数据中的缺失值
# 直接使用所有人年龄的中位数来填补
# 在处理之前,查看Age列的统计值
print(titanic_df.Age.describe())

# 重新载入原始数据
titanic_df=pd.read_csv("data/titanic.csv")

# 计算所有人年龄的均值
age_median1 = titanic_df.Age.median()

# 使用fillna填充缺失值,inplace=True表示在原数据titanic_df上直接进行修改
titanic_df.Age.fillna(age_median1,inplace=True)
#查看Age列的统计值
print(titanic_df.Age.describe())
#print(titanic_df.info())

# 考虑性别因素,分别用男女乘客各自年龄的中位数来填补
# 重新载入原始数据
titanic_df=pd.read_csv("data/titanic.csv")
# 分组计算男女年龄的中位数, 得到一个Series数据,索引为Sex
age_median2 = titanic_df.groupby('Sex').Age.median()
# 设置Sex为索引
titanic_df.set_index('Sex',inplace=True)
# 使用fillna填充缺失值,根据索引值填充
titanic_df.Age.fillna(age_median2, inplace=True)
# 重置索引,即取消Sex索引
titanic_df.reset_index(inplace=True)
# 查看Age列的统计值
print(titanic_df.Age.describe())

#同时考虑性别和舱位因素

# 重新载入原始数据
titanic_df=pd.read_csv("data/titanic.csv")
# 分组计算不同舱位男女年龄的中位数, 得到一个Series数据,索引为Pclass,Sex
age_median3 = titanic_df.groupby(['Pclass', 'Sex']).Age.median()
# 设置Pclass, Sex为索引, inplace=True表示在原数据titanic_df上直接进行修改
titanic_df.set_index(['Pclass','Sex'], inplace=True)
print(titanic_df)

# 使用fillna填充缺失值,根据索引值填充
titanic_df.Age.fillna(age_median3, inplace=True)
# 重置索引,即取消Pclass,Sex索引
titanic_df.reset_index(inplace=True)

# 查看Age列的统计值
titanic_df.Age.describe()

将连续型变量离散化

  • 连续型变量离散化是建模中一种常用的方法
  • 离散化指的是将某个变量的所在区间分割为几个小区间,落在同一个区间的观测值用同一个符号表示
  • 以年龄为例,最小值是0.42(婴儿),最大值是80,如果我们想产生一个五个级(levels),我们可使用cut或者qcut函数
  • cut函数将年龄的区间均匀分割为5分,而qcut则选取区间以至于每个区间里的观察值个数都是一样的(五等分), 这里演示中使用cut函数。
# 读取常用的包
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

#读取数据
titanic_df = pd.read_csv('data/titanic.csv')

#查看前五行数据
print(titanic_df.head())

# 数据的统计描述
# describe函数查看部分变量的分布
# 因为Survived是0-1变量,所以均值就是幸存人数的百分比,这个用法非常有用
print(titanic_df[["Survived","Age","SibSp","Parch"]].describe())

# 使用include=[np.object]来查看分类变量
# count: 非缺失值的个数
# unique: 非重复值得个数
# top: 最高频值
# freq: 最高频值出现次数

print(titanic_df.describe(include=[np.object]))

#不同舱位的分布情况是怎样的呢?
# 方法1: value_counts
# 查看不同舱位的分布
# 头等舱:24%; 二等舱:21%; 三等舱:55%
# value_counts 频数统计, len() 获取数据长度
print(titanic_df.Pclass.value_counts() / len(titanic_df))
# 总共有891个乘客
# Age有714个非缺失值,Cabin只有204个非缺失值。我们将会讲解如何处理缺失值
print(titanic_df.info())

#方法2:group_by
# sort_values 将结果排序
(titanic_df.groupby("Pclass").agg("size")/len(titanic_df)).sort_values(ascending=False)

# 填补年龄数据中的缺失值
# 直接使用所有人年龄的中位数来填补
# 在处理之前,查看Age列的统计值
print(titanic_df.Age.describe())

# 重新载入原始数据
titanic_df=pd.read_csv("data/titanic.csv")

# 计算所有人年龄的均值
age_median1 = titanic_df.Age.median()

# 使用fillna填充缺失值,inplace=True表示在原数据titanic_df上直接进行修改
titanic_df.Age.fillna(age_median1,inplace=True)
#查看Age列的统计值
print(titanic_df.Age.describe())
#print(titanic_df.info())

# 考虑性别因素,分别用男女乘客各自年龄的中位数来填补
# 重新载入原始数据
titanic_df=pd.read_csv("data/titanic.csv")
# 分组计算男女年龄的中位数, 得到一个Series数据,索引为Sex
age_median2 = titanic_df.groupby('Sex').Age.median()
# 设置Sex为索引
titanic_df.set_index('Sex',inplace=True)
# 使用fillna填充缺失值,根据索引值填充
titanic_df.Age.fillna(age_median2, inplace=True)
# 重置索引,即取消Sex索引
titanic_df.reset_index(inplace=True)
# 查看Age列的统计值
print(titanic_df.Age.describe())

#同时考虑性别和舱位因素

# 重新载入原始数据
titanic_df=pd.read_csv("data/titanic.csv")
# 分组计算不同舱位男女年龄的中位数, 得到一个Series数据,索引为Pclass,Sex
age_median3 = titanic_df.groupby(['Pclass', 'Sex']).Age.median()
# 设置Pclass, Sex为索引, inplace=True表示在原数据titanic_df上直接进行修改
titanic_df.set_index(['Pclass','Sex'], inplace=True)
print(titanic_df)

# 使用fillna填充缺失值,根据索引值填充
titanic_df.Age.fillna(age_median3, inplace=True)
# 重置索引,即取消Pclass,Sex索引
titanic_df.reset_index(inplace=True)

# 查看Age列的统计值
titanic_df.Age.describe()


###
#分析哪些因素会决定生还概率
###

# 舱位与生还概率
#计算每个舱位的生还概率
# 方法1:使用经典的分组-聚合-计算
# 注意:因为Survived是0-1函数,所以均值即表示生还百分比
print(titanic_df[['Pclass', 'Survived']].groupby('Pclass').mean() \
    .sort_values(by='Survived', ascending=False))

# 方法2:我们还可以使用pivot_table函数来实现同样的功能(本次课新内容)
# pivot table中文为数据透视表
# values: 聚合后被施加计算的值,这里我们施加mean函数
# index: 分组用的变量
# aggfunc: 定义施加的函数
print(titanic_df.pivot_table(values='Survived', index='Pclass', aggfunc=np.mean))

# 绘制舱位和生还概率的条形图
# 使用sns.barplot做条形图,图中y轴给出 Survived 均值的点估计
#sns.barplot(data=titanic_df,x='Pclass',y='Survived',ci=None)
# plt.show()

#####
#性别与生还概率
#####
# 方法1:groupby
print(titanic_df[["Sex", "Survived"]].groupby('Sex').mean() \
    .sort_values(by='Survived', ascending=False))
# 方法2:pivot_table
print(titanic_df.pivot_table(values="Survived",index='Sex',aggfunc=np.mean))

# 绘制条形图
#sns.barplot(data=titanic_df,x='Sex',y='Survived',ci=None)
#plt.show()


#####
#综合考虑舱位和性别的因素,与生还概率的关系
#####
# 方法1:groupby
print(titanic_df[['Pclass','Sex', 'Survived']].groupby(['Pclass', 'Sex']).mean())

# 方法2:pivot_table
titanic_df.pivot_table(values='Survived', index=['Pclass', 'Sex'], aggfunc=np.mean)

# 方法3:pivot_talbe
# columns指定另一个分类变量,只不过我们将它列在列里而不是行里,这也是为什么这个变量称为columns
print(titanic_df.pivot_table(values="Survived",index="Pclass",columns="Sex",aggfunc=np.mean))

#绘制条形图:使用sns.barplot
#sns.barplot(data=titanic_df,x='Pclass',y='Survived',hue='Sex',ci=None)
# plt.show()

# 绘制折线图:使用sns.pointplot
sns.pointplot(data=titanic_df,x='Pclass',y="Survived",hue="Sex",ci=None)
#plt.show()

####
#年龄与生还情况
####
#与上面的舱位、性别这些分类变量不同,年龄是一个连续的变量

#生还组和罹难组的年龄分布直方图
#使用seaborn包中的 FacetGrid().map() 来快速生成高质量图片
# col='Survived'指定将图片在一行中做出生还和罹难与年龄的关系图
sns.FacetGrid(titanic_df,col='Survived').\
    map(plt.hist,'Age',bins=20,normed=True)
# plt.show()


###
#将连续型变量离散化
###
#我们使用cut函数
#我们可以看到每个区间的大小是固定的,大约是16岁

titanic_df['AgeBand'] = pd.cut(titanic_df['Age'],5)
print(titanic_df.head())

#查看落在不同年龄区间里的人数
#方法1:value_counts(), sort=False表示不需要将结果排序
print(titanic_df.AgeBand.value_counts(sort=False))

#方法2:pivot_table
print(titanic_df.pivot_table(values='Survived',index='AgeBand',aggfunc='count'))

#查看各个年龄区间的生还率
print(titanic_df.pivot_table(values="Survived",index='AgeBand',aggfunc=np.mean))
sns.barplot(data=titanic_df,x='AgeBand',y='Survived',ci=None)
plt.xticks(rotation=60)
plt.show()


####
# 年龄、性别 与生还概率
####
# 查看落在不同区间里男女的生还概率
print(titanic_df.pivot_table(values='Survived',index='AgeBand', columns='Sex', aggfunc=np.mean))

sns.pointplot(data=titanic_df, x='AgeBand', y='Survived', hue='Sex', ci=None)
plt.xticks(rotation=60)

plt.show()

####
#年龄、舱位、性别 与生还概率
####
titanic_df.pivot_table(values='Survived',index='AgeBand', columns=['Sex', 'Pclass'], aggfunc=np.mean)



# 回顾sns.pointplot 绘制舱位、性别与生还概率的关系图
sns.pointplot(data=titanic_df, x='Pclass', y='Survived', hue='Sex', ci=None)

人工神经网络

https://keras.io

机器学习

特征工程

特征工程到底是什么?

图片描述
案例分析:共享单车需求
特征工程(feature engineering)

  • 数据和特征决定了机器学习的上限,而一个好的模型只是逼近那个上限而已
  • 我们的目标是尽可能得从原始数据上获取有用的信息,一些原始数据本身往往不能直接作为模型的变量。
  • 特征工程是利用数据领域的相关知识来创建能够使机器学习算法达到最佳性能的特征的过程。

日期型变量的处理

以datetime为例子,这个特征里包含了日期和时间点两个重要信息。我们还可以进一步从日期中导出其所对应的月份和星期数。

#租车人数是由哪些因素决定的?
#导入数据分析包
import numpy as np
import pandas as pd

#导入绘图工具包
import matplotlib.pyplot as plt
import seaborn as sns

#导入日期时间变量处理相关的工具包
import calendar
from datetime import datetime

# 读取数据
BikeData = pd.read_csv('data/bike.csv')


#####
#了解数据大小
#查看前几行/最后几行数据
#查看数据类型与缺失值
####
# 第一步:查看数据大小

print(BikeData.shape)

# 第二步:查看前10行数据
print(BikeData.head(10))


# 第三步:查看数据类型与缺失值
# 大部分变量为整数型,温度和风速为浮点型变量
# datetime类型为object,我们将在下面进一步进行处理
# 没有缺失值!
print(BikeData.info())


####
#日期型变量的处理
####

# 取datetime中的第一个元素为例,其数据类型为字符串,所以我们可以使用split方法将字符串拆开
# 日期+时间戳是一个非常常见的数据形式
ex = BikeData.datetime[1]
print(ex)

print(type(ex))

# 使用split方法将字符串拆开
ex.split()

# 获取日期数据
ex.split()[0]

# 首先获得日期,定义一个函数使用split方法将日期+时间戳拆分为日期和
def get_date(x):
    return(x.split()[0])

# 使用pandas中的apply方法,对datatime使用函数get_date
BikeData['date'] = BikeData.datetime.apply(get_date)

print(BikeData.head())

# 生成租车时间(24小时)
# 为了取小时数,我们需要进一步拆分
print(ex.split()[1])
#":"是分隔符
print(ex.split()[1].split(":")[0])

# 将上面的内容定义为get_hour的函数,然后使用apply到datatime这个特征上
def get_hour(x):
    return (x.split()[1].split(":")[0])
# 使用apply方法,获取整列数据的时间
BikeData["hour"] = BikeData.datetime.apply(get_hour)

print(BikeData.head())

####
# 生成日期对应的星期数
####
# 首先引入calendar中的day_name,列举了周一到周日
print(calendar.day_name[:])

#获取字符串形式的日期
dateString = ex.split()[0]

# 使用datatime中的strptime函数将字符串转换为日期时间类型
# 注意这里的datatime是一个包不是我们dataframe里的变量名
# 这里我们使用"%Y-%m-%d"来指定输入日期的格式是按照年月日排序,有时候可能会有月日年的排序形式
print(dateString)
dateDT = datetime.strptime(dateString,"%Y-%m-%d")
print(dateDT)
print(type(dateDT))

# 然后使用weekday方法取出日期对应的星期数
# 是0-6的整数,星期一对应0, 星期日对应6
week_day = dateDT.weekday()

print(week_day)
# 将星期数映射到其对应的名字上
print(calendar.day_name[week_day])


# 现在将上述的过程融合在一起变成一个获取星期的函数
def get_weekday(dateString):
    week_day = datetime.strptime(dateString,"%Y-%m-%d").weekday()
    return (calendar.day_name[week_day])

# 使用apply方法,获取date整列数据的星期
BikeData["weekday"] = BikeData.date.apply(get_weekday)

print(BikeData.head())


####
# 生成日期对应的月份
####

# 模仿上面的过程,我们可以提取日期对应的月份
# 注意:这里month是一个attribute不是一个函数,所以不用括号

def get_month(dateString):
    return (datetime.strptime(dateString,"%Y-%m-%d").month)
# 使用apply方法,获取date整列数据的月份
BikeData["month"] = BikeData.date.apply(get_month)
print(BikeData.head())

####
#数据可视化举例
####

#绘制租车人数的箱线图, 以及人数随时间(24小时)变化的箱线图
# 设置画布大小
fig = plt.figure(figsize=(18,5))

# 添加第一个子图
# 租车人数的箱线图
ax1 = fig.add_subplot(121)
sns.boxplot(data=BikeData,y="count")
ax1.set(ylabel="Count",title="Box Plot On Count")


# 添加第二个子图
# 租车人数和时间的箱线图
# 商业洞察:租车人数由时间是如何变化的?
ax2 = fig.add_subplot(122)
sns.boxplot(data=BikeData,y="count",x="hour")
ax2.set(xlabel="Hour",ylabel="Count",title="Box Plot On Count Across Hours")
plt.show()

图片描述

机器学习

  • 机器学习(Machine Learning)是人工智能的分支,其目标是通过算法从现有的数据中建立模型(学习)来解决问题。
  • 机器学习是一门交叉学科,涉及概率统计(probability and statistics),优化(optimization),和计算机编程(computer programming)等等。
  • 用途极为广泛:从预测信用卡违约风险,癌症病人五年生存概率到汽车无人驾驶,都有着机器学习的身影。
  • 备受重视:人们在决策分析的时候越来越多得用定量方法(quantitative approach)来衡量一个决策的优劣。

监督学习

  • 监督学习(Supervised Learning):从给定的训练数据集中学习出一个函数,当新的数据到来时,可以根据这个函数预测结果。监督学习的训练集(training data)要求是包括输入和输出,也可以说是特征和目标。
  • 监督学习中又可进一步分为两大类主要问题:预测与分类。房价预测是一个典型的预测问题,房价作为目标是一个连续型变量。信用卡违约预测是一个典型的分类问题,是否违约作为一个目标是一个分类变量。

无监督学习

  • 无监督学习(Unsupervised Learning):训练集没有人为标注的结果。我们从输入数据本身探索规律。
  • 无监督学习的例子包括图片聚类分析,文章主题分类,基因序列分析,和高纬数据(high dimensional data) 降维等等。

案例分析:波士顿地区房价
注意波士顿房价数据是scikit-learn中的Toy datasets 可通过函数datasets.load_boston()直接加载
图片描述

学习资源

机器学习教程 及 笔记
https://www.datacamp.com/
http://matplotlib.org/2.1.0/g...
https://www.kesci.com/
https://keras.io

竞赛

https://www.kaggle.com/
天池大数据竞赛和Kaggle、DataCastle的比较,哪个比较好?
天池新人实战赛

参考

The Python Tutorial
python写入csv文件的几种方法总结
常见安装第三方库问题
慕课网 Python在数据科学中的应用
慕课网 Python数据分析-基础技术篇
《利用python进行数据分析》
DataLearningTeam/PythonData
Visualization
使用 NumPy 进行科学计算
使用Python进行描述性统计
Documentation of scikit-learn 0.19.1
Seaborn tutorial
特征工程

阅读 3.2k

推荐阅读
镜心的小树屋
用户专栏

方寸湛然GitHub组织地址:[链接]

47 人关注
123 篇文章
专栏主页