0%

“古之善为士者,微妙玄通,深不可识。
夫唯不可识。
故强为之容:豫兮,若冬涉川;犹兮,若畏四邻;俨兮,其若客;涣兮,若冰之将释;孰兮,其若朴;旷兮,其若谷;浑兮,其若浊。
孰能浊以止,静之徐清?
孰能安以久,动之徐生?”1

在数据挖掘和数据分析中,经常会遇到需要知道个体数据间差异的大小,进而需要得到个体数据间的相似度,最常见的就是电商平台中对于物品的推荐以及内容平台中对于信息的推送等等。
相似度就是两个item之间的相似性,一般就是计算两个item的特征之间的距离,距离越大,相似度越小;距离越小,相似度越大;也可以两个向量间的夹角来表示,夹角越大,相似度越小;夹角越小,相似度越大;
常用的有以下四种方法:

  • 欧几里得距离(Eucledian Distance)或称 欧氏距离
  • 余弦相似度 (Cosine Similarity)
  • 杰卡德相似系数(Jaccard Similarity coefficient)
  • 皮尔逊相关系数(Pearson correlation)

欧几里得距离 or 欧氏距离

两个n维向量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的欧氏距离:
EuclideanDistance.png
python代码常用的有两种,一种使用numpay,一种使用scipy:

1
import numpy as np
2
x=np.random.random(8)
3
y=np.random.random(8)
4
d1=np.sqrt(np.sum(np.square(x-y)))
5
d1

输出:

1
1.1282380087788222
1
from scipy.spatial.distance import pdist
2
z=np.vstack([x,y])
3
d2=pdist(z)
4
d2

输出:

1
array([ 1.12823801])

余弦相似度 (Cosine Similarity)

也可以叫余弦相似度。 几何中夹角余弦可用来衡量两个向量方向的差异,机器学习中借用这一概念来衡量样本向量之间的差异。余弦取值范围为[-1,1]。求得两个向量的夹角,并得出夹角对应的余弦值,此余弦值就可以用来表征这两个向量的相似性。夹角越小,趋近于0度,余弦值越接近于1,它们的方向更加吻合,则越相似。当两个向量的方向完全相反夹角余弦取最小值-1。当余弦值为0时,两向量正交,夹角为90度。因此可以看出,余弦相似度与向量的幅值无关,只与向量的方向相关。
两个n维样本点a(x11,x12,…,x1n)和b(x21,x22,…,x2n)的夹角余弦:
CosineSimilarity.png

1
d3=np.dot(x,y)/(np.linalg.norm(x)*np.linalg.norm(y))
2
d3

输出:

1
0.70543665237781283
1
z=np.vstack([x,y])
2
d4=1-pdist(z,'cosine')
3
d4

输出:

1
array([ 0.70543665])

杰卡德相似系数(Jaccard Similarity coefficient)

杰卡德相似系数
JaccardSimilarity01.png

两个集合A和B的交集元素在A,B的并集中所占的比例,称为两个集合的杰卡德相似系数,用符号J(A,B)表示。杰卡德相似系数是衡量两个集合的相似度一种指标。

杰卡德距离
JaccardSimilarity02.png

与杰卡德相似系数相反的概念是杰卡德距离(Jaccard distance)。杰卡德距离用两个集合中不同元素占所有元素的比例来衡量两个集合的区分度。

杰卡德相似系数代码实现:

1
import numpy as np
2
from scipy.spatial.distance import pdist
3
x=np.random.random(8)>0.5
4
y=np.random.random(8)>0.5
5
6
x=np.asarray(x,np.int32)
7
y=np.asarray(y,np.int32)
8
9
#方法一:根据公式求解
10
up=np.double(np.bitwise_and((x != y),np.bitwise_or(x != 0, y != 0)).sum())
11
down=np.double(np.bitwise_or(x != 0, y != 0).sum())
12
d1=(up/down)
13
14
15
#方法二:根据scipy库求解
16
X=np.vstack([x,y])
17
d2=pdist(X,'jaccard')

皮尔逊相关系数(Pearson correlation)

皮尔逊相关系数的定义
PearsonCorrelation01.png
前面提到的余弦相似度只与向量方向有关,但它会受到向量的平移影响,在夹角余弦公式中如果将 x 平移到 x+1, 余弦值就会改变。怎样才能实现平移不变性?这就要用到皮尔逊相关系数(Pearson correlation),有时候也直接叫相关系数。
如果将夹角余弦公式写成:
PearsonCorrelation02.gif
表示向量x和向量y之间的夹角余弦,则皮尔逊相关系数则可表示为:
PearsonCorrelation03.gif
皮尔逊相关系数具有平移不变性和尺度不变性,计算出了两个向量(维度)的相关性。

1
import numpy as np
2
x=np.random.random(8)
3
y=np.random.random(8)
4
5
#方法一:根据公式求解
6
x_=x-np.mean(x)
7
y_=y-np.mean(y)
8
d1=np.dot(x_,y_)/(np.linalg.norm(x_)*np.linalg.norm(y_))
9
10
#方法二:根据numpy库求解
11
X=np.vstack([x,y])
12
d2=np.corrcoef(X)[0][1]

相关系数是衡量随机变量X与Y相关程度的一种方法,相关系数的取值范围是[-1,1]。相关系数的绝对值越大,则表明X与Y相关度越高。当X与Y线性相关时,相关系数取值为1(正线性相关)或-1(负线性相关)。

1:老子《道德经》第十五章,老子故里,中国鹿邑。

“将欲歙之,必固张之;将欲弱之,必固强之;将欲废之,必固举之;将欲取之,必固予之。
是谓微明。
柔弱胜刚强。
鱼不可脱于渊,国之利器不可以示人。”1

模式匹配

关于scala的模式匹配在上篇博客《从java(python)到scala的n种记忆》中有提及,但是模式匹配在scala中应用的地方太多了,有必要单独攒一篇文字来记录它。

模式匹配跟java中的switch-case绝对的相似,只是java中只能匹配值,而scala中的这个不仅能匹配值,而且可以匹配类型和类。

  • 按值匹配

    1
    def bigData(content:String):Unit = {
    2
        content match{
    3
            case "spark" => println("yeah!spark!")
    4
            case "kafka" => println("wow!kafka!")
    5
            case _ => println("anything else?")
    6
        }
    7
      }
    8
    def main(args: Array[String]) {
    9
        bigData("spark")
    10
        bigData("kafka")
    11
        bigData("zipkin")
    12
      }

    输出:

    1
    yeah!spark!
    2
    wow!kafka!
    3
    anything else?

    case 后面还可以加条件判断,不过貌似不会很常用。

  • 类型模式匹配

    1
    object Demo {
    2
       def main(args: Array[String]) {
    3
          println(matchTest("two"))
    4
          println(matchTest("test"))
    5
          println(matchTest(1))
    6
       }
    7
    8
       def matchTest(x: Any): Any = x match {
    9
          case 1 => "one"
    10
          case "two" => 2
    11
          case y: Int => "scala.Int"
    12
          case _ => "many"
    13
       }
    14
    }

    输出:

    1
    2
    2
    many
    3
    one
  • 样例类(case class)模式匹配
    Scala Case类只是常规类,默认情况下是不可变的,可通过模式匹配可分解。它使用相等(equal)方法在结构上比较实例。它不使用new关键字实例化对象。默认情况下,case类中列出的所有参数默认使用public和immutable修辞符。
    语法:

    1
    case class className(parameters)
    1
    case class CaseClass(a:Int, b:Int)  
    2
    3
    object Demo{  
    4
        def main(args:Array[String]){  
    5
            var c =  CaseClass(13,14)       // Creating object of case class  
    6
            println("a = "+c.a)               // Accessing elements of case class  
    7
            println("b = "+c.b)  
    8
        }  
    9
    }

    输出:

    1
    a = 13
    2
    b = 14

    Case类支持模式匹配。 所以,可以在模式中使用它。没有参数的case类将被声明为case对象而不是case类。 默认情况下,case对象是可序列化的。

    1
    trait SuperTrait  
    2
    case class CaseClass1(a:Int,b:Int) extends SuperTrait  
    3
    case class CaseClass2(a:Int) extends SuperTrait         // Case class  
    4
    case object CaseObject extends SuperTrait               // Case object  
    5
    object Demo{  
    6
        def main(args:Array[String]){  
    7
            callCase(CaseClass1(10,10))  
    8
            callCase(CaseClass2(10))  
    9
            callCase(CaseObject)  
    10
        }  
    11
        def callCase(f:SuperTrait) = f match{  
    12
            case CaseClass1(f,g)=>println("a = "+f+" b ="+g)  
    13
            case CaseClass2(f)=>println("a = "+f)  
    14
            case CaseObject=>println("No Argument")  
    15
        }  
    16
    }

    输出:

    1
    a = 10 b =10
    2
    a = 10
    3
    No Argument

    类型参数

    Scala中的类型参数,与java中的泛型类似。

    1
    class Person[T](val content:T){
    2
      def getContent(id:T)=id+"_"+content
    3
    }
    4
    ……
    5
    def main(args: Array[String]) {
    6
        val person_Str = new Person[String]("String")
    7
        println(person_Str.getContent("spark"))
    8
        val person_Int = new Person[Int](14)
    9
        println(person_Int.getContent(13))
    10
      }

    输出:

    1
    spark_String
    2
    13_14

    所以,我们使用类型参数,可以很好的指定特定值得输入类型,然后基于该类型进行一些操作,增加了程序的健壮性。Spark中的RDD就是这样的。
    上面只是一个简单的例子,scala的泛型[T]有如下六种方式:

  • scala的类和方法、函数都可以是泛型。

  • 关于对类型边界的限定分为上边界和下边界(对类进行限制)
    上边界:表达了泛型的类型必须是某种类型或者某种类的子类,语法为<:,例如T <: AnyVal表示泛型T的类型的最顶层类是AnyVal。
    下边界:表达了泛型的类型必须是某种类型或者某种类的父类,语法为>:,例如T >: S表示泛型T的类型必须是S的超类,下界的作用主要是保证类型安全。

  • “<%” :view bounds可以进行某种神秘的转换,把你的类型在没有知觉的情况下转换成目标类型
    如果希望类型变量界定能跨越类继承层次结构时,可以使用视图界定来实现的,其后面的原理是通过隐式转换来实现。视图界定利用<%符号来实现,例如后面的例子[T <% Person],T是Person继承的或者是能变成Person。

  • “T:classTag”:相当于动态类型,你使用时传入什么类型就是什么类型

  • 逆变和协变:-T和+T
    逆变和协变最容易理解的便是用List来理解。
    协变定义形式如:trait List[+T] {} 。当类型S是类型A的子类型时,则List[S]也可以认为是List[A}的子类型,
    即List[S]可以泛化为List[A]。
    逆变定义形式如:trait List[-T] {}
    当类型S是类型A的子类型,则Queue[A]反过来可以认为是Queue[S}的子类型。

  • “T:Ordering” :表示将T变成Ordering[T],可以直接用其方法进行比大小,可完成排序等工作

1:老子《道德经》第三十六章,老子故里,中国鹿邑。

“道常无为,而无不为。
侯王若能守之,万物将自化。
化而欲作,吾将镇之以无名之朴。
无名之朴,夫亦将不欲。
不欲以静,天下将自定。”1

对于scala的学习成本,大多会体现在对于隐式转换的理解应用上。隐式转换伴随着泛型,scala所有的神秘之处、优雅之处皆因于此。

隐式在scala中,应用场景会在如下四个方面:

  • 隐式参数
    1
    scala> def razor(implicit name:String) = name
    2
    razor: (implicit name: String)String
    直接调用razor方法
    1
    scala> razor
    2
    <console>:13: error: could not find implicit value for parameter name: String
    3
           razor
    4
           ^
    报错!编译器说无法为参数name找到一个隐式值
    定义一个隐式值后再调用razor方法
    1
    scala> implicit val iname = "Philips"
    2
    iname: String = Philips
    3
    4
    scala> razor
    5
    res12: String = Philips
    因为将iname变量标记为implicit,所以编译器会在方法省略隐式参数的情况下去搜索作用域内的隐式值作为缺少参数。
    但是如果此时你又重复定义一个隐式变量,再次调用方法时就会报错
    1
    scala> implicit val iname2 = "Gillette"
    2
    iname2: String = Gillette
    3
    4
    scala> razor
    5
    <console>:15: error: ambiguous implicit values:
    6
     both value iname of type => String
    7
     and value iname2 of type => String
    8
     match expected type String
    9
           razor
    10
           ^
    匹配失败,所以隐式转换必须满足无歧义规则,在声明隐式参数的类型是最好使用特别的或自定义的数据类型,不要使用Int,String这些常用类型,避免碰巧匹配。
  • 隐式函数
    1
    class Person(val name:String)
    2
    3
    class Engineer(val name:String,val salary:Double){
    4
      def mySalary(): Unit ={
    5
         println(name+",your monthly salary is is:"+salary)
    6
      }
    7
    }
    8
    9
    object Test {
    10
      def main(args: Array[String]): Unit = {
    11
        new Person("sutong").mySalary
    12
      }
    13
    }
    实例化一个person对象,然后调用mySalary方法时,此时编译是通不过的,因为person类没有mySalary方法。但是如果我们加入一个隐式函数就能时编译通过并能顺利运行,如下:
    1
    object Test {
    2
      implicit def person2Engineer(p:Person):Engineer = {
    3
        new Engineer(p.name,100000)
    4
      }
    5
      def main(args: Array[String]): Unit = {
    6
        new Person("sutong").mySalary
    7
      }
    8
    }
    输出:
    1
    sutong,your salary is:100000.0
    Scala会在报错前,去找隐式函数,例如我们定义的隐式函数,根据函数签名,主要是输入参数,找到了person2Engineer方法,并利用此方法将person对象转换为了Engineer对象,然后发现Engineer对象有mySalary方法,直接调用其mySalary方法,打印输出。运行后,Person对象和Engineer类型无任何关系。

约定:

虽然在定义implicit函数时scala并未要求要写明返回类型,但我们应写明返回类型,这样有助于代码阅读。

  • 隐式对象
    用implicit修饰的object就是隐式对象。
    1
    abstract class Template[T]{
    2
      def add(a:T,b:T):T
    3
    }
    4
    5
    abstract class SubTemplate[T] extends Template[T] {
    6
      def unit:T
    7
    }
    8
    9
    object Implicit_Object_Test {
    10
      def main(args: Array[String]): Unit = {
    11
        implicit object StringAdd extends SubTemplate[String]{
    12
          override def unit: String = ""
    13
          override def add(a:String,b:String):String = a concat b
    14
        }
    15
        implicit object IntAdd extends SubTemplate[Int]{
    16
          override def unit: Int = 0
    17
          override def add(a:Int,b:Int):Int = a+b
    18
        }
    19
    20
        def sum[T](x:List[T])(implicit m:SubTemplate[T]):T = {
    21
          if(x.isEmpty) m.unit
    22
          else m.add(x.head,sum(x.tail))
    23
        }
    24
    25
        println(sum(List(2,4,6,8,10)))
    26
        println(sum(List("a","b","c")))
    27
      }
    28
    }
    29
    输出:
    30
    30
    31
    abc
    首先定义了两个含有泛型的抽象类,Template是父类,而SubTempalte是子类,而这个子类有有两个子对象StringAdd和IntAdd,下面来看下主函数中定义的sum函数,它是一个含有泛型的函数,它的第一个参数是含有泛型的List类型的xs,第二个参数是含有泛型的SubTemplate类型的隐式参数m,函数返回值是一个泛型,首先,函数里先判断传入的第一个参数是否为空,若为空则调用隐式参数m,有由于scala可以自动进行类型推到,所以运行时,泛型T是一个确定类型,要么为Int要么为String,但是为空时,我们调用隐式参数m的unit是不同的,Int为0,而String为“”,所以我们定义了两个隐式对象对其进行处理,IntAdd隐式类复写了unit,使之为0,StringAdd隐式类复写了unit,使之为””,这样程序就可以正常执行了。同理,隐式对象方法对add方法进行复写,完成了sum操作。
  • 隐式类
    在scala2.10后提供了隐式类,可以使用implicit声明类,但是需要注意以下几点:

1.其所带的构造参数有且只能有一个
2.隐式类必须被定义在类,伴生对象和包对象里
3.隐式类不能是case class(case class在定义会自动生成伴生对象与2矛盾)
4.作用域内不能有与之相同名称的标示符

1
import scala.io.Source
2
import java.io.File
3
4
object Implicit_Class {
5
  import Context_Helper._
6
  def main(args: Array[String]) {
7
    println(1.add(2))  
8
    println(new File("I:\\aa.txt").read())
9
  }
10
}
11
12
object Context_Helper{
13
  implicit class ImpInt(tmp:Int){
14
    def add(tmp2: Int) = tmp + tmp2
15
  }
16
  implicit class FileEnhance(file:File){
17
    def read() = Source.fromFile(file.getPath).mkString
18
  }
19
}

其中1.add(2)这个可以这样理解:

当 1.add(2) 时,scala 编译器不会立马报错,而检查当前作用域有没有 用implicit 修饰的,同时可以将Int作为参数的构造器,并且具有方法add的类,经过查找 发现 ImpInt 符合要求,利用隐式类 ImpInt 执行add 方法。

归纳一下

  • 隐式转换的时机
    a.当方法中的参数的类型与目标类型不一致时
    b.当对象调用类中不存在的方法或成员时,编译器会自动将对象进行隐式转换
  • 隐式解析机制
    a.首先会在当前代码作用域下查找隐式实体(隐式方法 隐式类 隐式对象)
    b.如果第一条规则查找隐式实体失败,会继续在隐式参数的类型的作用域里查找
  • 隐式转换的前提
    a.不存在二义性
    b.隐式操作不能嵌套使用
    c.代码能够在不使用隐式转换的前提下能编译通过,就不会进行隐式转换

1:老子《道德经》第三十七章,老子故里,中国鹿邑。

“道冲,而用之或不盈。
渊兮,似万物之宗。
挫其锐,解其纷,和其光,同其尘。
湛兮,似或存,吾不知其谁之子,象帝之先。”^ddj

###可重入
若一个程序或子程序可以“安全的被并行执行(Parallel computing)”,则称其为可重入(reentrant或re-entrant)的。即当该子程序正在运行时,可以再次进入并执行它(并行执行时,个别的执行结果,都符合设计时的预期)。可重入概念是在单线程操作系统的时代提出的。

ReentrantLock默认情况下为不公平锁

1
private ReentrantLock lock = new ReentrantLock();//公平锁
2
private ReentrantLock lock = new ReentrantLock(true);//不公平锁

不公平锁与公平锁的区别:
公平情况下,操作会排一个队按顺序执行,来保证执行顺序。(会消耗更多的时间来排队)
不公平情况下,是无序状态允许插队,jvm会自动计算如何处理更快速来调度插队。(如果不关心顺序,这个速度会更快)

使用场景

ReentrantLock的使用场景,通常有如下几个:

  • 发现该操作已经在执行中则不再执行(有状态执行)
    1
    private ReentrantLock lock = new ReentrantLock();//公平锁
    2
    ...
    3
    if(lock.tryLock()){//如果已经被锁,则会立即返回false不会等待,忽略锁住的业务操作执行
    4
        try{
    5
            ////业务操作
    6
        }finally{    
    7
            lock.unlock();
    8
        }
    9
    }
    10
    ...
  • 如果发现该操作已经在执行,等待一个一个执行(同步执行,类似synchronized)
  • 如果发现该操作已经在执行,则尝试等待一段时间,等待超时则不执行(尝试等待执行)
    1
    private ReentrantLock lock = new ReentrantLock();//公平锁
    2
    ...
    3
    if(lock.tryLock(5,TimeUnit.SECONDS)){//尝试等待5秒
    4
        try{
    5
            ////业务操作
    6
        }finally{    
    7
            lock.unlock();
    8
        }
    9
    }
  • 如果发现该操作已经在执行,等待执行。这时可中断正在进行的操作立刻释放锁继续下一操作
    synchronized与Lock在默认情况下是不会响应中断(interrupt)操作,会继续执行完。lockInterruptibly()提供了可中断锁来解决此问题。(场景2的另一种改进,没有超时,只能等待中断或执行完毕)

这种情况主要用于取消某些操作对资源的占用

源码分析

1
/** 同步器:内部类Sync的一个引用 */
2
private final Sync sync;
3
4
/**
5
 * 创建一个非公平锁
6
 */
7
public ReentrantLock() {
8
    sync = new NonfairSync();
9
}
10
11
/**
12
 * 创建一个锁
13
 * @param fair true-->公平锁  false-->非公平锁
14
 */
15
public ReentrantLock(boolean fair) {
16
    sync = (fair)? new FairSync() : new NonfairSync();
17
}

三个内部类Sync/NonfairSync/FairSync

1
/**
2
     * 该锁同步控制的一个基类.下边有两个子类:非公平机制和公平机制.使用了AbstractQueuedSynchronizer类的
3
     */
4
    static abstract class Sync extends AbstractQueuedSynchronizer
5
6
    /**
7
     * 非公平锁同步器
8
     */
9
    final static class NonfairSync extends Sync
10
11
    /**
12
     * 公平锁同步器
13
     */
14
    final static class FairSync extends Sync

ReentrantLock:lock()

1
/**
2
     *获取一个锁
3
     *三种情况:
4
     *1、如果当下这个锁没有被任何线程(包括当前线程)持有,则立即获取锁,锁数量==1,之后再执行相应的业务逻辑
5
     *2、如果当前线程正在持有这个锁,那么锁数量+1,之后再执行相应的业务逻辑
6
     *3、如果当下锁被另一个线程所持有,则当前线程处于休眠状态,直到获得锁之后,当前线程被唤醒,锁数量==1,再执行相应的业务逻辑
7
     */
8
    public void lock() {
9
        sync.lock();//调用NonfairSync(非公平锁)或FairSync(公平锁)的lock()方法
10
    }

NonfairSync:lock()

1
/**
2
         * 1)首先基于CAS将state(锁数量)从0设置为1,如果设置成功,设置当前线程为独占锁的线程;-->请求成功-->第一次插队
3
         * 2)如果设置失败(即当前的锁数量可能已经为1了,即在尝试的过程中,已经被其他线程先一步占有了锁),这个时候当前线程执行acquire(1)方法
4
         * 2.1)acquire(1)方法首先调用下边的tryAcquire(1)方法,在该方法中,首先获取锁数量状态,
5
         * 2.1.1)如果为0(证明该独占锁已被释放,当下没有线程在使用),这个时候我们继续使用CAS将state(锁数量)从0设置为1,如果设置成功,当前线程独占锁;-->请求成功-->第二次插队;当然,如果设置不成功,直接返回false
6
         * 2.2.2)如果不为0,就去判断当前的线程是不是就是当下独占锁的线程,如果是,就将当前的锁数量状态值+1(这也就是可重入锁的名称的来源)-->请求成功
7
         *
8
         * 下边的流程一句话:请求失败后,将当前线程链入队尾并挂起,之后等待被唤醒。
9
         *
10
         * 2.2.3)如果最后在tryAcquire(1)方法中上述的执行都没成功,即请求没有成功,则返回false,继续执行acquireQueued(addWaiter(Node.EXCLUSIVE), arg)方法
11
         * 2.2)在上述方法中,首先会使用addWaiter(Node.EXCLUSIVE)将当前线程封装进Node节点node,然后将该节点加入等待队列(先快速入队,如果快速入队不成功,其使用正常入队方法无限循环一直到Node节点入队为止)
12
         * 2.2.1)快速入队:如果同步等待队列存在尾节点,将使用CAS尝试将尾节点设置为node,并将之前的尾节点插入到node之前
13
         * 2.2.2)正常入队:如果同步等待队列不存在尾节点或者上述CAS尝试不成功的话,就执行正常入队(该方法是一个无限循环的过程,即直到入队为止)-->第一次阻塞
14
         * 2.2.2.1)如果尾节点为空(初始化同步等待队列),创建一个dummy节点,并将该节点通过CAS尝试设置到头节点上去,设置成功的话,将尾节点也指向该dummy节点(即头节点和尾节点都指向该dummy节点)
15
         * 2.2.2.1)如果尾节点不为空,执行与快速入队相同的逻辑,即使用CAS尝试将尾节点设置为node,并将之前的尾节点插入到node之前
16
         * 最后,如果顺利入队的话,就返回入队的节点node,如果不顺利的话,无限循环去执行2.2)下边的流程,直到入队为止
17
         * 2.3)node节点入队之后,就去执行acquireQueued(final Node node, int arg)(这又是一个无限循环的过程,这里需要注意的是,无限循环等于阻塞,多个线程可以同时无限循环--每个线程都可以执行自己的循环,这样才能使在后边排队的节点不断前进)
18
         * 2.3.1)获取node的前驱节点p,如果p是头节点,就继续使用tryAcquire(1)方法去尝试请求成功,-->第三次插队(当然,这次插队不一定不会使其获得执行权,请看下边一条),
19
         * 2.3.1.1)如果第一次请求就成功,不用中断自己的线程,如果是之后的循环中将线程挂起之后又请求成功了,使用selfInterrupt()中断自己
20
         * (注意p==head&&tryAcquire(1)成功是唯一跳出循环的方法,在这之前会一直阻塞在这里,直到其他线程在执行的过程中,不断的将p的前边的节点减少,直到p成为了head且node请求成功了--即node被唤醒了,才退出循环)
21
         * 2.3.1.2)如果p不是头节点,或者tryAcquire(1)请求不成功,就去执行shouldParkAfterFailedAcquire(Node pred, Node node)来检测当前节点是不是可以安全的被挂起,
22
         * 2.3.1.2.1)如果node的前驱节点pred的等待状态是SIGNAL(即可以唤醒下一个节点的线程),则node节点的线程可以安全挂起,执行2.3.1.3)
23
         * 2.3.1.2.2)如果node的前驱节点pred的等待状态是CANCELLED,则pred的线程被取消了,我们会将pred之前的连续几个被取消的前驱节点从队列中剔除,返回false(即不能挂起),之后继续执行2.3)中上述的代码
24
         * 2.3.1.2.3)如果node的前驱节点pred的等待状态是除了上述两种的其他状态,则使用CAS尝试将前驱节点的等待状态设为SIGNAL,并返回false(因为CAS可能会失败,这里不管失败与否,都返回false,下一次执行该方法的之后,pred的等待状态就是SIGNAL了),之后继续执行2.3)中上述的代码
25
         * 2.3.1.3)如果可以安全挂起,就执行parkAndCheckInterrupt()挂起当前线程,之后,继续执行2.3)中之前的代码
26
         * 最后,直到该节点的前驱节点p之前的所有节点都执行完毕为止,我们的p成为了头节点,并且tryAcquire(1)请求成功,跳出循环,去执行。
27
         * (在p变为头节点之前的整个过程中,我们发现这个过程是不会被中断的)
28
         * 2.3.2)当然在2.3.1)中产生了异常,我们就会执行cancelAcquire(Node node)取消node的获取锁的意图。
29
         */
30
        final void lock() {
31
            if (compareAndSetState(0, 1))//如果CAS尝试成功
32
                setExclusiveOwnerThread(Thread.currentThread());//设置当前线程为独占锁的线程
33
            else
34
                acquire(1);
35
        }

FairSync:lock()

1
final void lock() {
2
          acquire(1);
3
}

AbstractQueuedSynchronizer:acquire(int arg)就是非公平锁使用的那个方法
FairSync:tryAcquire(int acquires)

1
/**
2
  * 获取公平锁的方法
3
  * 1)获取锁数量c
4
  * 1.1)如果c==0,如果当前线程是等待队列中的头节点,使用CAS将state(锁数量)从0设置为1,如果设置成功,当前线程独占锁-->请求成功
5
  * 1.2)如果c!=0,判断当前的线程是不是就是当下独占锁的线程,如果是,就将当前的锁数量状态值+1(这也就是可重入锁的名称的来源)-->请求成功
6
  * 最后,请求失败后,将当前线程链入队尾并挂起,之后等待被唤醒。
7
  */
8
 protected final boolean tryAcquire(int acquires) {
9
     final Thread current = Thread.currentThread();
10
     int c = getState();
11
     if (c == 0) {
12
         if (isFirst(current) && compareAndSetState(0, acquires)) {
13
             setExclusiveOwnerThread(current);
14
             return true;
15
         }
16
     }
17
     else if (current == getExclusiveOwnerThread()) {
18
         int nextc = c + acquires;
19
         if (nextc < 0)
20
             throw new Error("Maximum lock count exceeded");
21
         setState(nextc);
22
         return true;
23
     }
24
     return false;
25
 }

最后,如果请求失败后,将当前线程链入队尾并挂起,之后等待被唤醒,下边的代码与非公平锁一样。

“大道泛兮,其可左右。
万物恃之而生而不辞,功成不名有。
衣养万物而不为主,常无欲,可名于小;万物归焉而不为主,可名为大。
是以圣人之能成大也,以其不为大也,故能成大。”1

本文的出发点是记录scala与传统java以及python的不同之处。

行结尾方式 抑或 换行符

跟java不同的地方在于,每一行不必以“;”结尾,除了一个行如果写多条语句时,前面的语句必须以“;”结尾。

1
val rdd = sc.parallelize([1,2,3,4]);println(rdd)

注释

完全跟java一样,/**/用于多行;//用于单行。

package

引入包,有两种方式:

  • 跟java相同
    1
    package com.c-goshine.sh.demo;
  • 有些类似c#
    1
    package com.cgoshine.sh.demo{
    2
    3
    }
    使用这种方式可以在一个文件中定义个包。

    import

    跟python有些像,import可以写在文件的任何地方。
    导入某个包下的所有成员,这个跟java的方式有些不同,用“_”来代替java的“*”,如:
    1
    import com.cgoshine.sh.demo._ //引入包内所有成员

如果想引用包里的几个成员,可以使用选择器selector

import java.awt.{Color, Font}
// 重命名成员
import java.util.{HashMap => JavaHashMap}
// 隐藏成员
import java.util.{HashMap => _, _} // 引入了util包的所有成员,但是HashMap被隐藏了

注意:默认情况下,Scala 总会引入 java.lang._ 、 scala._ 和 Predef._,这里也能解释,为什么以scala开头的包,在使用时都是省去scala.的。

数据类型

scala与java有着相同的数据类型。

数据类型 描述
Byte 8位有符号补码整数。数值区间为 -128 到 127
Short 16位有符号补码整数。数值区间为 -32768 到 32767
Int 32位有符号补码整数。数值区间为 -2147483648 到 2147483647
Long 64位有符号补码整数。数值区间为 -9223372036854775808 到 9223372036854775807
Float 32位IEEE754单精度浮点数
Double 64位IEEE754单精度浮点数
Char 16位无符号Unicode字符, 区间值为 U+0000 到 U+FFFF
String 字符序列
Boolean true或false
Unit 表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。
Null null 或空引用
Nothing Nothing类型在Scala的类层级的最低端;它是任何其他类型的子类型。
Any Any是所有其他类的超类
AnyRef AnyRef类是Scala里所有引用类(reference class)的基类

变量声明

用var声明变量;用val声明常量

格式:var VariableName : DataType [= Initial Value]

1
var ss:String [="rzaor"]
2
var ss //裸奔方式

访问修饰符

public private protected

  • private
    默认public,其中private比java要严格(在嵌套类情况下,外层类甚至不能访问被嵌套类的私有成员)。
    1
    class Outer{
    2
        class Inner{
    3
        private def f(){println("f")}
    4
        class InnerMost{
    5
            f() // 正确
    6
            }
    7
        }
    8
        (new Inner).f() //错误
    9
    }
  • protected
    同样也比java的要严格。因为它只允许保护成员在定义了该成员的的类的子类中被访问。而在java中,用protected关键字修饰的成员,除了定义了该成员的类的子类可以访问,同一个包里的其他类也可以进行访问。
    1
    package p{
    2
    class Super{
    3
        protected def f() {println("f")}
    4
        }
    5
        class Sub extends Super{
    6
            f()
    7
        }
    8
        class Other{
    9
            (new Super).f() //错误
    10
        }
    11
    }
  • 作用域保护
    1
    private[x]
    2
    protected[x]
    理解为:如果写成private[x],读作”这个成员除了对[…]中的类或[…]中的包中的类及它们的伴生对像可见外,对其它所有类都是private。这种技巧在横跨了若干包的大型项目中非常有用,它允许你定义一些在你项目的若干子包中可见但对于项目外部的客户却始终不可见的东西。
    1
    package bobsrocckets{
    2
        package navigation{
    3
            private[bobsrockets] class Navigator{
    4
             protected[navigation] def useStarChart(){}
    5
             class LegOfJourney{
    6
                 private[Navigator] val distance = 100
    7
                 }
    8
                private[this] var speed = 200
    9
                }
    10
            }
    11
            package launch{
    12
            import navigation._
    13
            object Vehicle{
    14
            private[launch] val guide = new Navigator
    15
            }
    16
        }
    17
    }
    类Navigator被标记为private[bobsrockets]就是说这个类对包含在bobsrockets包里的所有的类和对象可见。
    比如说,从Vehicle对象里对Navigator的访问是被允许的,因为对象Vehicle包含在包launch中,而launch包在bobsrockets中,相反,所有在包bobsrockets之外的代码都不能访问类Navigator。

位运算符

位运算符用来对二进制位进行操作,~,&,|,^分别为取反,按位与与,按位与或,按位与异或运算。
如果指定 A = 60; 及 B = 13; 两个变量对应的二进制为:

1
A = 0011 1100
2
3
B = 0000 1101
4
5
-------位运算----------
6
7
A&B = 0000 1100
8
9
A|B = 0011 1101
10
11
A^B = 0011 0001
12
13
~A  = 1100 0011

Scala 中的按位运算法则如下:

运算符 描述 实例
& 按位与运算符 (a & b) 输出结果 12 ,二进制解释: 0000 1100
| 按位或运算符 (a | b) 输出结果 61 ,二进制解释: 0011 1101
^ 按位异或运算符 (a ^ b) 输出结果 49 ,二进制解释: 0011 0001
~ 按位取反运算符 (~a ) 输出结果 -61 ,二进制解释: 1100 0011, 在一个有符号二进制数的补码形式。
<< 左移动运算符 a << 2 输出结果 240 ,二进制解释: 1111 0000
>> 右移动运算符 a >> 2 输出结果 15 ,二进制解释: 0000 1111
>>> 无符号右移 A >>>2 输出结果 15, 二进制解释: 0000 1111

函数 方法

Scala 有函数和方法,二者在语义上的区别很小。Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量。换句话来说在类中定义的函数即是方法。

  • 函数声明
    1
    def functionName ([参数列表]) : [return type]
  • 函数定义
    1
    def functionName ([参数列表]) : [return type] = {
    2
       function body
    3
       return [expr]
    4
    }
    如果函数没有返回值,可以返回为 Unit,这个类似于 Java 的 void。
    1
    object add{
    2
       def addInt( a:Int, b:Int ) : Int = {
    3
          var sum:Int = 0
    4
          sum = a + b
    5
          return sum
    6
       }
    7
      def printMe( ) : Unit = {
    8
          println("Hello, Scala!")
    9
       }
    10
    }

    闭包

    闭包是一个函数,返回值依赖于声明在函数外部的一个或多个变量。
    如下面这段匿名的函数:
    1
    val multiplier = (i:Int) => i * 10
    函数体内有一个变量 i,它作为函数的一个参数。如下面的另一段代码:
    1
    val multiplier = (i:Int) => i * factor
    在 multiplier 中有两个变量:i 和 factor。其中的一个 i 是函数的形式参数,在 multiplier 函数被调用时,i 被赋予一个新的值。然而,factor不是形式参数,而是自由变量,考虑下面代码:
    1
    var factor = 3  
    2
    val multiplier = (i:Int) => i * factor
    这样定义的函数变量 multiplier 成为一个”闭包”,因为它引用到函数外面定义的变量,定义这个函数的过程是将这个自由变量捕获而构成一个封闭的函数。
    1
    object Test {  
    2
       def main(args: Array[String]) {  
    3
          println( "muliplier(1) value = " +  multiplier(1) )  
    4
          println( "muliplier(2) value = " +  multiplier(2) )  
    5
       }  
    6
       var factor = 3  
    7
       val multiplier = (i:Int) => i * factor  
    8
    }

函数的闭包就是当函数的参数超出其作用域时,我们还能对参数进行访问。

1
scala> def iscala(content:String) = (message:String) => println(content + " "+ message)
2
iscala: (content: String)String => Unit
3
4
scala> val func1 = iscala("spark")
5
func1: String => Unit = $$Lambda$1228/248295195@3dceec83
6
7
scala> func1("hadoop")
8
spark hadoop
9
10
scala> func1("hbase")
11
spark hbase

在调用func1时,将之前的content参数的值延续了下来。

字符串连接

1
string1.concat(string2);

同样你也可以使用加号(+)来连接

  • 创建格式化字符串
    1
    object Test {
    2
       def main(args: Array[String]) {
    3
          var floatVar = 12.456
    4
          var intVar = 2000
    5
          var stringVar = "scala multi-paradigm!"
    6
          var fs = printf("浮点型变量为 " +
    7
                       "%f, 整型变量为 %d, 字符串为 " +
    8
                       " %s", floatVar, intVar, stringVar)
    9
          println(fs)
    10
       }
    11
    }

    for循环

    1
    for( var x <- Range ){
    2
       statement(s);
    3
    }
    Range 可以是一个数字区间表示 i to j ,或者 i until j。左箭头 <- 用于为变量 x 赋值。
    举个例子:
    1
    object Test {
    2
       def main(args: Array[String]) {
    3
          var a = 0;
    4
          // for 循环
    5
          for( a <- 1 to 10){
    6
             println( "Value of a: " + a );
    7
          }
    8
       }
    9
    }

类和对象

Scala中的类不声明为public,一个Scala源文件中可以有多个类。

1
class Point(xc: Int, yc: Int) {
2
  ……
3
}

继承

Scala继承一个基类跟Java很相似, 但我们需要注意以下几点:

  • 重写一个非抽象方法必须使用override修饰符。
  • 只有主构造函数才可以往基类的构造函数里写参数。
  • 在子类中重写超类的抽象方法时,你不需要使用override关键字。

继承会继承父类的所有属性和方法,Scala 只允许继承一个父类。

单例对象 & 伴生对象

Scala单例对象是十分重要的,不像Java一样,有静态类、静态成员、静态方法,但是Scala提供了object对象,这个object对象类似于Java的静态类,它的成员、它的方法都默认是静态的。
如果object的静态成员要被外界访问,则该成员不能被private修饰。
伴生对象首先是一个单例对象,单例对象用关键字object定义。在Scala中,单例对象分为两种,一种是并未自动关联到特定类上的单例对象,称为独立对象 (Standalone Object);另一种是关联到一个类上的单例对象,该单例对象与该类共有相同名字,则这种单例对象称为伴生对象(Companion Object),对应类称为伴生类。

Trait(特性)

Scala Trait(特征) 相当于 Java 的接口,实际上它比接口还功能强大。
与接口不同的是,它还可以定义属性和方法的实现。
一般情况下Scala的类只能够继承单一父类,但是如果是 Trait(特征) 的话就可以继承多个,从结果来看就是实现了多重继承。
Trait(特征) 定义的方式与类类似,但它使用的关键字是 trait。

1
package com.cgoshine.sh.demo.scala
2
3
trait Equal {
4
  def isEqual(x:Any):Boolean
5
  def isNotEqual(x:Any):Boolean = !isEqual(x)
6
}

isEqual 方法没有定义方法的实现,isNotEqual定义了方法的实现。子类继承特征可以实现未被实现的方法。所以其实 Scala Trait(特征)更像 Java 的抽象类。

implements这个在scala中到目前为止还没见到,即使“实现”Trait中也是用的extends

1
class Point(xc: Int, yc: Int) extends Equal {
2
……
3
}

模式匹配

Scala 提供了强大的模式匹配机制,应用也非常广泛。
match 对应 Java 里的 switch,但是写在选择器表达式之后。即: 选择器 match {备选项}
一个模式匹配包含了一系列备选项,每个都开始于关键字 case。每个备选项都包含了一个模式及一到多个表达式。箭头符号 => 隔开了模式和表达式。

1
object Test {
2
   def main(args: Array[String]) {
3
      println(matchTest(3))
4
5
   }
6
   def matchTest(x: Int): String = x match {
7
      case 1 => "one"
8
      case 2 => "two"
9
      case _ => "many"
10
   }
11
}

“_”,默认的全匹配备选项,即没有找到其他匹配时的匹配项,类似 switch 中的 default。

  • 使用样例类
    使用了case关键字的类定义就是就是样例类(case classes),样例类是种特殊的类,经过优化以用于模式匹配。
    1
    object Test {
    2
       def main(args: Array[String]) {
    3
           val alice = new Person("Alice", 25)
    4
        val bob = new Person("Bob", 32)
    5
           val charlie = new Person("Charlie", 32)
    6
    7
        for (person <- List(alice, bob, charlie)) {
    8
            person match {
    9
                case Person("Alice", 25) => println("Hi Alice!")
    10
                case Person("Bob", 32) => println("Hi Bob!")
    11
                case Person(name, age) =>
    12
                   println("Age: " + age + " year, name: " + name + "?")
    13
             }
    14
          }
    15
       }
    16
       // 样例类
    17
       case class Person(name: String, age: Int)
    18
    }
    在声明样例类时,下面的过程自动发生了:

    构造器的每个参数都成为val,除非显式被声明为var,但是并不推荐这么做;
    在伴生对象中提供了apply方法,所以可以不使用new关键字就可构建对象;
    提供unapply方法使模式匹配可以工作;
    生成toString、equals、hashCode和copy方法,除非显示给出这些方法的定义。

正则表达式

Scala 通过 scala.util.matching 包中的 Regex 类来支持正则表达式。

1
import scala.util.matching.Regex
2
3
object Test {
4
   def main(args: Array[String]) {
5
      val pattern = "Scala".r
6
      val str = "Scala is Scalable and cool"
7
8
      println(pattern findFirstIn str)
9
   }
10
}

使用 String 类的 r() 方法构造了一个Regex对象,然后使用 findFirstIn 方法找到首个匹配项。
如果需要查看所有的匹配项可以使用 findAllIn 方法。你可以使用 mkString( ) 方法来连接正则表达式匹配结果的字符串,并可以使用管道(|)来设置不同的模式:

1
import scala.util.matching.Regex
2
3
object Test {
4
   def main(args: Array[String]) {
5
      val pattern = new Regex("(S|s)cala")  // 首字母可以是大写 S 或小写 s
6
      val str = "Scala is scalable and cool"
7
8
      println((pattern findAllIn str).mkString(","))   // 使用逗号 , 连接返回结果
9
   }
10
}

输出结果为:

1
$ scalac Test.scala
2
$ scala Test
3
Scala,scala

如果你需要将匹配的文本替换为指定的关键词,可以使用 replaceFirstIn( ) 方法来替换第一个匹配项,使用 replaceAllIn( ) 方法替换所有匹配项。

1
object Test {
2
   def main(args: Array[String]) {
3
      val pattern = "(S|s)cala".r
4
      val str = "Scala is scalable and cool"
5
6
      println(pattern replaceFirstIn(str, "Java"))
7
   }
8
}

Scala 的正则表达式继承了 Java 的语法规则,Java 则大部分使用了 Perl 语言的规则。

  • 规则:
表达式 匹配规则
^ 匹配输入字符串开始的位置。
$ 匹配输入字符串结尾的位置。
. 匹配除”\r\n”之外的任何单个字符。
[…] 字符集。匹配包含的任一字符。例如,”[abc]”匹配”plain”中的”a”。
[^…] 反向字符集。匹配未包含的任何字符。例如,”[^abc]”匹配”plain”中”p”,”l”,”i”,”n”。
\A 匹配输入字符串开始的位置(无多行支持)
\z 字符串结尾(类似$,但不受处理多行选项的影响)
\Z 字符串结尾或行尾(不受处理多行选项的影响)
re* 重复零次或更多次
re+ 重复一次或更多次
re? 重复零次或一次
re{ n} 重复n次
re{ n,}
re{ n, m} 重复n到m次
a|b 匹配 a 或者 b
(re) 匹配 re,并捕获文本到自动命名的组里
(?: re) 匹配 re,不捕获匹配的文本,也不给此分组分配组号
(?> re) 贪婪子表达式
\w 匹配字母或数字或下划线或汉字
\W 匹配任意不是字母,数字,下划线,汉字的字符
\s 匹配任意的空白符,相等于 [\t\n\r\f]
\S 匹配任意不是空白符的字符
\d 匹配数字,类似 [0-9]
\D 匹配任意非数字的字符
\G 当前搜索的开头
\n 换行符
\b 通常是单词分界位置,但如果在字符类里使用代表退格
\B 匹配不是单词开头或结束的位置
\t 制表符
\Q 开始引号:\Q(a+b)3\E 可匹配文本 “(a+b)3”。
\E 结束引号:\Q(a+b)3\E 可匹配文本 “(a+b)3”。
  • 实例:
实例 描述
. 匹配除”\r\n”之外的任何单个字符。
[Rr]uby 匹配 “Ruby” 或 “ruby”
rub[ye] 匹配 “ruby” 或 “rube”
[aeiou] 匹配小写字母 :aeiou
[0-9] 匹配任何数字,类似 [0123456789]
[a-z] 匹配任何 ASCII 小写字母
[A-Z] 匹配任何 ASCII 大写字母
[a-zA-Z0-9] 匹配数字,大小写字母
[^aeiou] 匹配除了 aeiou 其他字符
[^0-9] 匹配除了数字的其他字符
\d 匹配数字,类似: [0-9]
\D 匹配非数字,类似: [^0-9]
\s 匹配空格,类似: [ \t\r\n\f]
\S 匹配非空格,类似: [^ \t\r\n\f]
\w 匹配字母,数字,下划线,类似: [A-Za-z0-9_]
\W 匹配非字母,数字,下划线,类似: [^A-Za-z0-9_]
ruby? 匹配 “rub” 或 “ruby”: y 是可选的
ruby* 匹配 “rub” 加上 0 个或多个的 y。
ruby+ 匹配 “rub” 加上 1 个或多个的 y。
\d{3} 刚好匹配 3 个数字。
\d{3,} 匹配 3 个或多个数字。
\d{3,5} 匹配 3 个、4 个或 5 个数字。
\D\d+ 无分组: + 重复 \d
(\D\d)+/ 分组: + 重复 \D\d 对
([Rr]uby(, )?)+ 匹配 “Ruby”、”Ruby, ruby, ruby”,等等

异常处理

Scala 的异常处理和其它语言比如 Java 类似。

1
throw new FileNotFoundException

如果有异常发生,catch字句是按次序捕捉的。因此,在catch字句中,越具体的异常越要靠前,越普遍的异常越靠后。 如果抛出的异常不在catch字句中,该异常则无法处理,会被升级到调用者处。
捕捉异常的catch子句,语法与其他语言中不太一样。在Scala里,借用了模式匹配的思想来做异常的匹配,因此,在catch的代码里,是一系列case字句:

1
import java.io.FileReader
2
import java.io.FileNotFoundException
3
import java.io.IOException
4
5
object Test {
6
   def main(args: Array[String]) {
7
      try {
8
         val f = new FileReader("input.txt")
9
      } catch {
10
         case ex: FileNotFoundException =>{
11
            println("Missing file exception")
12
         }
13
         case ex: IOException => {
14
            println("IO Exception")
15
         }
16
      }
17
   }
18
}
  • finally 语句
    finally 语句用于执行不管是正常处理还是有异常发生时都需要执行的步骤。
    1
    import java.io.FileReader
    2
    import java.io.FileNotFoundException
    3
    import java.io.IOException
    4
    5
    object Test {
    6
       def main(args: Array[String]) {
    7
          try {
    8
             val f = new FileReader("input.txt")
    9
          } catch {
    10
             case ex: FileNotFoundException => {
    11
                println("Missing file exception")
    12
             }
    13
             case ex: IOException => {
    14
                println("IO Exception")
    15
             }
    16
          } finally {
    17
             println("Exiting finally...")
    18
          }
    19
       }
    20
    }

    提取器(Extractor)

    提取器是从传递给它的对象中提取出构造该对象的参数。
    Scala 提取器是一个带有unapply方法的对象。unapply方法算是apply方法的反向操作:unapply接受一个对象,然后从对象中提取值,提取的值通常是用来构造该对象的值。
    1
    object Test {
    2
       def main(args: Array[String]) {
    3
    4
          println ("Apply 方法 : " + apply("Zara", "gmail.com"));
    5
          println ("Unapply 方法 : " + unapply("Zara@gmail.com"));
    6
          println ("Unapply 方法 : " + unapply("Zara Ali"));
    7
    8
       }
    9
       // 注入方法 (可选)
    10
       def apply(user: String, domain: String) = {
    11
          user +"@"+ domain
    12
       }
    13
    14
       // 提取方法(必选)
    15
       def unapply(str: String): Option[(String, String)] = {
    16
          val parts = str split "@"
    17
          if (parts.length == 2){
    18
             Some(parts(0), parts(1))
    19
          }else{
    20
             None
    21
          }
    22
       }
    23
    }
    输出:
    1
    $ scalac Test.scala
    2
    $ scala Test
    3
    Apply 方法 : Zara@gmail.com
    4
    Unapply 方法 : Some((Zara,gmail.com))
    5
    Unapply 方法 : None

Options Some None

Some和None都是Options的子类,Scala鼓励你在变量和函数返回值可能不会引用任何值的时候使用Option类型。在没有值的时候,使用None;如果有值可以引用,就使用Some来包含这个值。

1
scala> val capitals = Map("France"->"Paris", "Japan"->"Tokyo", "China"->"Beijing")
2
capitals: scala.collection.immutable.Map[String,String] = Map(France -> Paris, Japan -> Tokyo, China -> Beijing)
3
4
scala> capitals get "France"
5
res0: Option[String] = Some(Paris)
6
7
scala> capitals get "Germany"
8
res1: Option[String] = None

当程序回传Some的时候,代表函式返回一个String,你可以调用get()函数获得那个String,如果程序返回的是None,则代表没有字符串可以给你。
在返回None,也就是没有String给你的时候,如果你还硬要调用get()来取得 String 的话,Scala一样是会抛出一个NoSuchElementException异常给你的。
我们也可以选用另外一个方法,getOrElse。这个方法在这个Option是Some的实例时返回对应的值,而在是None的实例时返回传入的参数。换句话说,传入getOrElse的参数实际上是默认返回值。

1
scala> capitals get "Germany" get
2
warning: there was one feature warning; re-run with -feature for details
3
java.util.NoSuchElementException: None.get
4
  ……
5
6
scala> capitals get "France" get
7
warning: there was one feature warning; re-run with -feature for details
8
res3: String = Paris
9
10
scala> (capitals get "Germany") getOrElse "Oops"
11
res7: String = Oops
12
13
scala> capitals get "France" getOrElse "Oops"
14
res8: String = Paris

文件 I/O

Scala 进行文件写操作,直接用的都是 java中 的 I/O 类 (java.io.File):

1
import java.io._
2
3
object Test {
4
   def main(args: Array[String]) {
5
      val writer = new PrintWriter(new File("demo.txt" ))
6
7
      writer.write("com.cgoshine.sh.demo")
8
      writer.close()
9
   }
10
}
  • 从屏幕读取输入
    1
    object Test {
    2
       def main(args: Array[String]) {
    3
          print("input your company's name : " )
    4
          val line = Console.readLine
    5
    6
          println("thanks,your input is: " + line)
    7
       }
    8
    }
  • 从文件读取
    从文件读取内容非常简单。我们可以使用 Scala 的 Source 类及伴生对象来读取文件。
    1
    import scala.io.Source
    2
    3
    object Test {
    4
       def main(args: Array[String]) {
    5
          println("文件内容为:" )
    6
    7
          Source.fromFile("test.txt" ).foreach{
    8
             print
    9
          }
    10
       }
    11
    }

1:老子《道德经》第三十四章,老子故里,中国鹿邑。

“为学日益,为道日损。
损之又损,以至于无为。
无为而无不为。
取天下常以无事,及其有事,不足以取天下。”1

列表

字符串索引分片

格式:[lower:upper:step]
[lower,upper)

列表与整数相乘

1
l  = [3,5,'gradient','dropout','l2']
2
l * 2

output:

1
[3, 5, 'gradient', 'dropout', 'l2', 3, 5, 'gradient', 'dropout', 'l2']

列表可以通过索引和分片进行修改

1
l[0] = ['deep learning']
2
l

output:

1
[['deep learning'], 5, 'gradient', 'dropout', 'l2']
1
l[0:2] = ['DeepLearning','regularizatioin']
2
l

output:

1
['DeepLearning', 'regularizatioin', 'gradient', 'dropout', 'l2']

列表中某个元素出现的次数

1
l2 = ["DeepLearning",'normalization']
2
l + l2
3
l3 = l + l2
4
l3

output:

1
['DeepLearning',
2
 'regularizatioin',
3
 'gradient',
4
 'dropout',
5
 'l2',
6
 'DeepLearning',
7
 'normalization']
1
l3.count('DeepLearning')

output:

1
2

元组

跟列表类似,但不可变,且有序。

(12,) #定义单个元素的元组。

1
a = (12,)
2
print a
3
print type(a)

output:

1
(10,)
2
<type 'tuple'>
1
a = (12)
2
print type(a)

output:

1
<type 'int'>

将列表转换为元组

1
tuple(l)

output:

1
('DeepLearning', 'regularizatioin', 'gradient', 'dropout', 'l2')

不可变集合

frozenset

1
flight_distance = {}
2
city_pair = frozenset(['Los Angeles', 'New York'])
3
flight_distance[city_pair] = 2498
4
flight_distance[frozenset(['Austin', 'Los Angeles'])] = 1233
5
flight_distance[frozenset(['Austin', 'New York'])] = 1515
6
flight_distance

output:

1
{frozenset({'Austin', 'New York'}): 1515,
2
 frozenset({'Austin', 'Los Angeles'}): 1233,
3
 frozenset({'Los Angeles', 'New York'}): 2498}

切片

切片的引用机制

1
a = array([0,1,2,3,4])
2
b = a[2:4]

引用机制意味着,Python并没有为 b 分配新的空间来存储它的值,而是让 b 指向了 a 所分配的内存空间,因此,改变 b 会改变 a 的值:

1
b[0] = 10
2
a

output:

1
array([ 0,  1, 10,  3,  4])

可用用.copy()来产生一个复制来避免这种及联修改:

1
b = a[2:4].copy()

花式索引

1
a = array([[ 0, 1, 2, 3, 4, 5],
2
           [10,11,12,13,14,15],
3
           [20,21,22,23,24,25],
4
           [30,31,32,33,34,35],
5
           [40,41,42,43,44,45],
6
           [50,51,52,53,54,55]])
7
a

output:

1
array([[ 0,  1,  2,  3,  4,  5],
2
       [10, 11, 12, 13, 14, 15],
3
       [20, 21, 22, 23, 24, 25],
4
       [30, 31, 32, 33, 34, 35],
5
       [40, 41, 42, 43, 44, 45],
6
       [50, 51, 52, 53, 54, 55]])

对于二维花式索引,我们需要给定 row 和 col 的值:

1
a[(0,1,2,3,4), (1,2,3,4,5)]
2
output:
3
array([ 1, 12, 23, 34, 45]) #返回的是一条次对角线上的5个值。
1
a[3:, [0,2,5]]
2
output:
3
array([[30, 32, 35],
4
       [40, 42, 45],
5
       [50, 52, 55]]) #返回的是最后三行的第1,3,5列。

与切片不同,花式索引返回的是原对象的一个复制而不是引用。

squeeze 方法除去多余的轴

squeeze 返回一个将所有长度为1的维度去除的新数组。

1 :老子《道德经》第四十八章,老子故里,中国鹿邑。

“希言自然。
故飘风不终朝,骤雨不终日。
孰为此者?
天地,天地尚不能久,而况于人乎?
故从事于道者同于道,德者同于德,失者同于失。
故同于道者,道亦得之;同于失,道亦失之。
信不足,焉有不信。”1

本文对如下方法进行记录:(持续更新)

  • zip
  • bincount
  • enumerate

zip

zip函数接受任意多个(包括0个和1个)序列作为参数,返回一个tuple列表。

1
import numpy as np
2
x = [2,5,3,5]
3
y = [1,3,2,5]
4
z = [8,7,9,0]
5
# i = (3,4,5,6)
6
i = list(zip(x,y,z))
7
i

output:

1
[(2, 1, 8), (5, 3, 7), (3, 2, 9), (5, 5, 0)]

bincount

1
numpy.bincount(x, weights=None, minlength=None)

数组x以及返回的数据bins,bins的数量比x中的最大值+1,bins[i]=x[i]在x中出现的次数。
比如:

1
import numpy as np
2
x = [2,5,3,5]
3
c = np.bincount(x)
4
c

output:

1
array([0, 0, 1, 1, 0, 2])
2
# 0在x中出现0次
3
# 1在x中出现0次
4
# 2在x中出现1次
5
# 3在x中出现1次
6
# 4在x中出现0次
7
# 5在x中出现1次

看一下设置了weights的情况:
bins[i]=sum(x[i]*w[i])

1
import numpy as np
2
x = [2,5,3,5]
3
w = [.4,.3,.7,.1]
4
c = np.bincount(x,w)
5
c

output:

1
array([ 0. ,  0. ,  0.4,  0.7,  0. ,  0.4])

参数minlength貌似只有在minlength>x.len的时候有效,表示bins数组的最小长度。
这篇文章可以移步去看看 - bincount详解

enumerate

  • enumerate()是python的内置函数
  • enumerate在字典上是枚举、列举的意思
  • 对于一个可迭代的(iterable)/可遍历的对象(如列表、字符串),enumerate将其组成一个索引序列,利用它可以同时获得索引和值
  • enumerate多用于在for循环中得到计数
    1
    enum = ['我','爱','北京','天安门']
    2
    for index,s in enumerate(enum):
    3
        print('index=%d s=%s'% (index,s))
    output:
    1
    index=0 s=我
    2
    index=1 s=爱
    3
    index=2 s=北京
    4
    index=3 s=天安门

1 :老子《道德经》,老子故里,中国鹿邑。

“唯之与阿,相去几何?
善之与恶,相去何若?
人之所畏,不可不畏。
荒兮,其未央哉!
众人熙熙,如享太牢,如春登台。
我独泊兮,其未兆,如婴儿之未孩;傫傫兮,若无所归!
众人皆有余,而我独若遗。
我愚人之心也哉!”1

在用scikit-learn做增量训练的时候,一般都会事先实现一个文件流迭代器,将一个大数据文件分多次使用2,会用到yield关键字,当一个函数或方法中出现了yield之后,这个函数或方法就会被看作一个生成器(generators)了,可以使用.next()方法获取内容。

通常意义上的函数或者方法,在程序的其他部分调用一旦返回,函数的生命周期也就结束,再次调用的时候,函数会重新被执行。而今天要介绍的yield最大的特点就是,函数的执行会被多次调用,下一次调用总是从上一次yield返回的地方开始执行,也就是多次被调用的函数拥有了记忆功能。

被赋予生成器的函数,只会被“完整”的调用一次,也即执行到函数体的最后一行指令。
1.函数第一次调用,会在函数体中yield的地方返回。
2.函数第二次调用,程序会从上次返回的地方接着往下继续执行,直到再次遇到yield

文件流迭代器

1
def iter_minibatches(data_stream, minibatch_size=1000):
2
    '''
3
    迭代器
4
    给定文件流(比如一个大文件),每次输出minibatch_size行,默认选择1k行
5
    将输出转化成numpy输出,返回X, y
6
    '''
7
    X = []
8
    y = []
9
    cur_line_num = 0
10
11
    csvfile = file(data_stream, 'rb')
12
    reader = csv.reader(csvfile)
13
    for line in reader:
14
        y.append(float(line[0]))
15
        X.append(line[1:])  # 这里要将数据转化成float类型
16
17
        cur_line_num += 1
18
        if cur_line_num >= minibatch_size:
19
            X, y = np.array(X), np.array(y)  # 将数据转成numpy的array类型并返回
20
            yield X, y  # 每次调用,如迭代未结束,则都是在此处返回
21
            X, y = [], []
22
            cur_line_num = 0
23
    csvfile.close()
24
25
# 生成测试文件
26
minibatch_test_iterators = iter_minibatches(test_file, minibatch_size=5000)
27
X_test, y_test = minibatch_test_iterators.next()  # 得到一份测试文件

使用文件流迭代器进行增量训练

1
from sklearn.linear_model import SGDClassifier
2
sgd_clf = SGDClassifier()  # SGDClassifier的参数设置可以参考sklearn官网
3
minibatch_train_iterators = iter_minibatches(data_part_file, minibatch_size=2000) # 文件批量迭代器
4
5
for i, (X_train, y_train) in enumerate(minibatch_train_iterators):
6
    # 使用 partial_fit ,并在第一次调用 partial_fit 的时候指定 classes
7
    sgd_clf.partial_fit(X_train, y_train, classes=np.array([0, 1]))
8
    print("{} time".format(i))  # 当前次数
9
    print("{} score".format(sgd_clf.score(X_test, y_test)))  # 在测试集上看效果

关于 yield 和 generators的概念 ,我觉得下面两篇帖子讲的挺好的,可以移步去看看:
提高你的Python: 解释 yield 和 Generators(生成器)
彻底理解Python中的yield

1 :老子《道德经》第二十章,老子故里,中国鹿邑。
2 :文件大到你一次性load到内存,会报内存不足而无法进行机器训练的时候。

“视之不见名曰夷,听之不闻名曰希,搏之不得名曰微。
此三者不可致诘,故混而为一。
一者,其上不皦,其下不昧。
绳绳不可名,复归于无物,是谓无状之状、无物之象,是谓惚恍。
迎之不见其首,随之不见其后。
执古之道,以御今之有,能知古始,是谓道纪。”1

SciPy

世界上著名的Python开源科学计算库。
官网(scipy.org):能啃英文的还是经常去这里看看。

SciPy函数库在NumPy库的基础上增加了众多的数学、科学以及工程计算中常用的库函数。它的不同子模块相应于不同的应用,像插值、积分、优化、图像处理、统计、特殊函数等等。

常用子模块

子模块 描述
scipy.cluster 聚类工具:矢量量化 / K-均值
scipy.constants 物理和数学常数
scipy.fftpack 快速傅里叶变换
scipy.integrate 数值积分
scipy.interpolate 插值:进行数据处理和可视化分析的常见操作,基于Python的SciPy支持一维和二维的插值运算。
scipy.io 数据输入输出
scipy.linalg 线性代数函数库,如:解线性方程组、最小二乘解、特征值和特征向量、奇异值分解等
scipy.ndimage n维图像包,提供了有关数学形态学的方法
scipy.odr 正交距离回归
scipy.optimize 优化和拟合库
scipy.signal 信号处理
scipy.sparse 稀疏矩阵
scipy.spatial 空间数据结构和算法
scipy.special 特殊数学函数
scipy.stats 统计

使用scipy之前要先导入包,建议不能像numpy那样全部导入,使用哪个子模块导入哪个子模块,如下:

1
import numpy as np
2
import pandas as pd
3
from scipy import io as spio

scipy.io文件的输入和输出

numpy、pandas、scipy.io均可以对文件进行操作。

  • numpy

np.load()
np.loadtxt()
np.genfromtxt()
np.recfromcsv()
np.recfromtxt()
……

  • pandas

pd.read_csv()
pd.read_excel()
pd.read_html()
……

  • scipy.io

    spio.loadmat()
    spio.savemat()

对上述方法的使用,在之后的分解文章中在介绍,现在先以spio举个例子,创建一个3行4列的矩阵,保存然后读取:

1
a = np.arange(12).reshape(3,4)
2
spio.savemat('file.mat',{'a':a})
3
datas = spio.loadmat('file.mat',struct_as_record=True)
4
datas

输出:

1
{'__globals__': [],
2
 '__header__': b'MATLAB 5.0 MAT-file Platform: posix, Created on: Sun Mar 18 10:41:36 2018',
3
 '__version__': '1.0',
4
 'a': array([[ 0,  1,  2,  3],
5
        [ 4,  5,  6,  7],
6
        [ 8,  9, 10, 11]])}

统计:分析随机数

scipy.stats包括统计工具和随机过程的概率过程。各个随机过程的随机数生成器可以从numpy.random中找到。
生成20个正态分布的随机数:

1
from scipy import stats
2
generates = stats.norm.rvs(size=20)
3
generates

输出:

1
array([ 0.09644491, -0.07552055,  2.4406988 ,  0.22137236, -0.2266991 ,
2
        1.93962117,  0.57879661, -0.03147269, -0.19289511,  0.40454166,
3
        0.668479  , -1.27321257, -1.55462663, -0.73369392,  0.55564607,
4
        0.85396381, -2.17697731, -1.02549411,  0.19205101,  2.7793757 ])

还记得reshape()方法吗,现在强化记忆一下,将generates改变为一个4行5列的矩阵:

1
generates.reshape(4,5)

输出:

1
array([[ 0.09644491, -0.07552055,  2.4406988 ,  0.22137236, -0.2266991 ],
2
       [ 1.93962117,  0.57879661, -0.03147269, -0.19289511,  0.40454166],
3
       [ 0.668479  , -1.27321257, -1.55462663, -0.73369392,  0.55564607],
4
       [ 0.85396381, -2.17697731, -1.02549411,  0.19205101,  2.7793757 ]])

接下来,我们拟合生成的一维数据,来生成均值和标准差:

1
mean,std = stats.norm.fit(generates)
2
mean,std

输出:

1
(0.17201995571492329, 1.2122988177111329)

stats.norm.rvs(size=xxx,loc=xxx,scale=xxx)有三个参数,其中loc为均值,scale为标准差

上述生成的正态分布的数据数量太小,我们增加到size=1000,来看几个校验方法:

1
array([  5.17903592e-01,  -4.84819825e-01,  -2.17331819e+00,
2
        -2.71978120e-03,   3.43398473e-01,  -1.53672137e+00,
3
        -7.80230954e-01,  -1.38493510e-01,   8.64678941e-01,
4
        -5.23193564e-01,   1.00355735e+00,   9.93139686e-02,
5
         4.46330129e-01,  -1.95042024e-01,  -7.78248002e-01,
6
         4.94678411e-01,   9.24668576e-01,   9.91269886e-01,
7
        -3.34111264e-01,   5.35049208e-01,   4.66624215e-01,
8
         8.74805164e-01,   1.21823570e-01,   5.81397820e-01,
9
        -4.45018479e-01,   1.04672648e-01,   7.56344139e-01,
10
         1.60198846e-01,  -1.46477267e-01,  -5.80502049e-01,
11
         3.99681665e-02,   2.67920793e+00,  -1.49332545e+00,
12
        -1.39485255e+00,  -1.62184979e-01,  -3.05899731e-02,
13
         4.97657829e-02,  -2.30222899e-01,  -9.49411984e-01,
14
        -1.31184285e+00,  -1.41967163e-01,  -4.34813954e-01,
15
         7.38725143e-01,   4.00598883e-01,   4.36436960e-01,
16
        -4.09986450e-01,  -2.07197222e-01,  -3.25044931e-01,
17
        -7.43910151e-01,  -6.13570624e-01,  -1.26727223e+00,
18
        -3.73803851e-01,  -8.48694345e-01,  -2.75244179e+00,
19
        -9.64321271e-01,   7.00534558e-01,   1.86793945e-01,
20
         7.46039130e-01,  -8.10518097e-01,   1.67235474e+00,
21
        -1.50856260e+00,   5.20941828e-01,  -7.67878811e-02,
22
         2.32584136e+00,   1.49835809e+00,  -9.05440571e-01,
23
        -1.24178395e+00,   2.43911036e-01,  -1.20667049e+00,
24
        -9.16536280e-01,  -4.49705301e-02,   2.30834507e-01,
25
        -6.92527685e-02,  -5.85348401e-02,   4.23071961e-01,
26
        -1.07815974e-01,   5.28821852e-01,  -3.22449511e-01,
27
        -7.12439336e-01,  -1.11656371e+00,   1.20476418e+00,
28
         2.19543599e+00,  -2.04023860e+00,   1.83482542e+00,
29
        -1.49249174e+00,  -2.68834446e-01,   1.95818755e-01,
30
        -3.16677583e-01,  -3.52805238e-01,   7.55090436e-01,
31
         2.11162353e+00,  -1.53078202e+00,   8.45645296e-01,
32
        -5.20684353e-01,   8.41674068e-01,   1.27422749e+00,
33
        -7.00928060e-01,  -5.80290714e-01,   1.00358607e+00,
34
         3.58235810e-01,  -8.06690609e-01,  -1.97432494e-01,
35
        -1.85253776e+00,   1.21471527e+00,  -1.32575833e+00,
36
         2.20498984e-01,  -7.59459595e-01,   6.54102341e-01,
37
        -1.91811635e-01,  -2.17006655e+00,   1.22757153e+00,
38
        -1.46243654e-01,  -6.36676291e-01,   3.02682605e-01,
39
         1.36671612e+00,   1.57930512e+00,   4.04263941e-01,
40
         1.28662572e+00,   2.49968315e-01,   4.06608797e-01,
41
        -8.93212197e-01,   1.63066508e+00,   1.23779907e+00,
42
        -7.84025604e-01,   3.12265366e-02,   6.51420464e-01,
43
         1.78509544e-01,  -2.68839046e-01,   1.15181648e-01,
44
        -7.85364176e-01,   1.25247067e+00,   7.72137479e-01,
45
        -1.18110763e+00,  -1.78637662e-01,  -1.13501810e+00,
46
        -2.69113774e+00,   2.43586397e-01,   1.07776230e+00,
47
        -1.33571329e+00,   1.56412663e+00,   7.68541531e-01,
48
        -3.88497111e-01,  -4.13440012e-01,   1.48619082e+00,
49
        -2.81005932e+00,   4.76974689e-01,  -4.83140098e-02,
50
        -2.09960292e+00,  -1.21598418e+00,   5.96742283e-01,
51
         9.15847172e-01,   2.25765097e-03,   1.54535341e+00,
52
        -1.47931509e+00,  -2.10377317e+00,  -1.45037025e+00,
53
         4.57123894e-01,  -1.94574739e+00,  -6.80606280e-01,
54
         4.76905629e-01,  -1.23517489e+00,  -6.88355573e-01,
55
         9.43119808e-01,   1.67302968e+00,   7.11875143e-01,
56
         1.64127917e+00,  -2.94041677e-01,   1.54103126e-01,
57
        -5.85416826e-01,   2.05999042e+00,   1.18738940e+00,
58
         1.99531518e-01,  -2.11101357e+00,  -1.09363755e+00,
59
         1.67983335e+00,   2.99285489e-01,   1.27744550e+00,
60
         7.36959152e-01,   1.39125694e+00,  -7.56751182e-01,
61
        -5.90793756e-01,  -3.86542077e-02,   1.81986351e+00,
62
        -1.06014546e+00,  -1.32346285e+00,  -7.39927880e-01,
63
         1.38212086e+00,  -5.88060104e-01,  -2.88610199e+00,
64
         6.45039997e-01,   8.05223241e-01,   1.50847871e+00,
65
         5.66306325e-01,  -2.22879103e-02,  -5.32065838e-01,
66
         9.29596147e-01,  -1.00062920e+00,  -7.22940989e-01,
67
        -6.88290586e-01,   1.49974723e-01,  -3.69190936e-01,
68
         6.43570526e-01,   1.40973583e+00,  -1.09694233e+00,
69
        -1.04788396e+00,   1.19138652e+00,  -2.64696938e-01,
70
         5.66860287e-01,   1.94722056e+00,   7.82355235e-01,
71
        -9.22911261e-01,  -7.43748090e-01,  -7.18312223e-01,
72
         3.61035218e-01,  -8.02051485e-01,  -1.25629229e+00,
73
        -1.11254930e+00,  -2.17500089e+00,  -5.61117834e-01,
74
         7.75492006e-01,   2.35203990e-01,   4.92911832e-01,
75
        -4.41602973e-01,  -1.43134294e+00,   1.24202334e+00,
76
        -1.27805897e+00,  -9.99866924e-01,  -1.71438632e+00,
77
        -1.79810070e+00,  -1.03384505e+00,  -7.38840610e-01,
78
         2.59881883e+00,   7.58599225e-01,  -2.91227055e-03,
79
        -1.08525899e+00,  -5.77098348e-01,   6.44084281e-02,
80
         1.75831702e+00,  -5.28591510e-01,   7.91843955e-01,
81
        -1.61140464e-01,   5.41977031e-01,  -2.29088856e-01,
82
        -1.94228622e-01,   7.53444460e-01,  -1.88985082e-01,
83
         1.58162684e+00,  -3.77083620e-01,   2.17144773e-01,
84
         1.02065186e+00,   4.34620425e-01,  -1.39747820e+00,
85
        -1.61820516e+00,   1.56519909e+00,   1.17291478e+00,
86
         9.61580854e-01,  -1.12329763e+00,  -7.24531012e-01,
87
        -8.60033707e-01,  -4.65461266e-01,   2.43657234e-01,
88
         1.74302788e+00,   1.45065256e-01,   5.57160946e-01,
89
        -3.26106670e-01,   2.32550557e-01,   1.06177286e+00,
90
        -6.52730310e-01,   5.12634301e-02,   7.23664099e-03,
91
        -5.97796521e-01,   2.94120803e-01,  -2.00167304e+00,
92
        -1.67558293e+00,  -6.90594381e-01,   8.05322517e-01,
93
         5.99708010e-01,   1.39946854e+00,  -9.12745996e-01,
94
         1.75628885e-01,  -9.52621164e-01,  -1.63553595e+00,
95
        -5.73909001e-02,  -2.13752327e-01,   9.08843189e-01,
96
         7.54338387e-01,   6.86448693e-01,   6.37414903e-01,
97
        -1.31553804e-01,  -6.14035005e-02,   3.17722855e-01,
98
         1.00010564e+00,   5.66189109e-01,  -3.31229887e-01,
99
        -1.26784197e+00,   5.65865115e-01,  -1.34827415e+00,
100
        -2.51836250e-02,   2.35383999e+00,  -1.25618785e+00,
101
        -8.50225265e-01,   1.85219586e-02,  -1.19282292e+00,
102
         1.79456724e-01,  -7.46712449e-01,   2.14327724e+00,
103
        -1.88544573e+00,  -9.50946030e-01,   1.29378603e-01,
104
        -2.16246079e+00,   1.50783186e+00,   2.31836239e-01,
105
         3.67135954e-01,   9.25395949e-01,  -7.43659199e-01,
106
        -4.63261176e-01,   9.17578865e-01,   6.31962811e-01,
107
         9.28821246e-01,   2.66833595e-01,   8.04378911e-01,
108
         3.66038122e-01,   6.52047153e-01,   1.56307516e+00,
109
        -8.89518014e-01,   3.75768229e-01,  -1.09131872e+00,
110
         4.55578487e-01,  -7.76866845e-01,   1.80204670e-02,
111
        -2.21759004e+00,   8.42415305e-01,   3.01510583e-02,
112
        -7.76409734e-02,  -4.11547372e-01,  -7.55102539e-01,
113
         2.10526334e-01,  -1.58522602e+00,  -1.35755283e+00,
114
        -8.58103811e-01,  -6.07561434e-01,   4.98475784e-01,
115
        -4.65715879e-01,   6.33148206e-01,   2.60342758e-01,
116
         5.99091782e-01,  -2.26842082e+00,   1.40177396e+00,
117
        -1.10198446e+00,   1.97454968e+00,   1.08095331e+00,
118
         1.02132766e+00,   1.17832728e+00,   9.30481505e-01,
119
        -1.38002873e+00,  -6.23477342e-01,   7.77572604e-01,
120
        -4.16849947e-02,   5.85935975e-02,  -3.43723693e-01,
121
        -1.29803389e+00,  -7.85437549e-01,   2.09918513e+00,
122
        -8.32242053e-02,   1.34756860e+00,   4.20666337e-01,
123
        -6.23077815e-01,   3.83333826e-01,   1.07637533e+00,
124
        -5.36798669e-01,   2.26184723e-01,  -1.71843124e+00,
125
         2.88628271e+00,  -1.66953870e+00,  -1.04128898e+00,
126
         7.29756517e-02,   9.16548743e-01,   1.00785434e+00,
127
         8.87834244e-01,   8.51919889e-01,  -3.92304884e-01,
128
        -2.90512265e-01,   5.32853057e-01,  -7.79351441e-01,
129
        -3.38995321e-01,  -1.78560587e-01,  -1.47718052e-01,
130
        -1.22337547e+00,  -4.14363367e-01,   1.78478385e+00,
131
         8.81224994e-01,  -2.86509296e-01,  -1.47140331e+00,
132
         2.00232111e-01,  -1.08666985e+00,   8.80514936e-01,
133
         8.45693941e-01,  -1.26209911e+00,  -1.43224161e+00,
134
         1.29518395e+00,   7.95465444e-01,   5.34646568e-01,
135
        -1.54851329e-01,  -1.34519089e-01,   8.43642647e-01,
136
        -7.02888200e-01,   1.10989002e+00,   7.10434593e-01,
137
         1.27288284e+00,  -7.02412620e-01,  -2.47260071e-02,
138
         1.86315225e+00,   3.18732128e-01,   2.85852319e-01,
139
        -2.89281323e-02,   1.64308914e+00,   6.78905592e-01,
140
        -2.23898207e+00,   6.45227361e-01,  -2.10722006e-01,
141
        -5.15334081e-02,   5.21718062e-01,  -4.28589133e-01,
142
        -3.32994850e-01,  -9.96564936e-01,   4.43139233e-02,
143
         8.34243415e-01,   2.17024275e-01,   6.48832946e-01,
144
         1.39552210e+00,   5.45378253e-01,   1.23680500e+00,
145
         1.36330855e+00,  -6.91938875e-01,  -1.32466443e+00,
146
         1.40977288e-01,   1.87758626e+00,   3.10942400e-01,
147
        -5.41959267e-01,   1.65385704e+00,   9.33377795e-01,
148
         8.91428028e-02,  -8.52805953e-01,   1.58607271e-01,
149
        -5.52939995e-01,   3.30720367e-01,  -9.75222073e-02,
150
         9.08906746e-01,  -4.77320009e-01,  -6.70020450e-01,
151
        -1.72473895e+00,   1.25450455e-02,   1.54247857e-02,
152
         4.77084668e-01,   9.74026348e-01,   4.66092420e-01,
153
        -1.86742467e-01,   5.19324577e-02,  -1.79982729e+00,
154
        -3.79270866e-01,   1.94272791e-02,  -2.28700755e-02,
155
        -1.44835613e+00,  -6.77897503e-01,  -3.76212765e-01,
156
         8.90054522e-01,   1.25702761e+00,  -1.17640677e-01,
157
         1.73785564e+00,   3.47620655e-01,  -9.67679848e-01,
158
         9.38381020e-01,  -2.02956574e+00,   1.03903973e-01,
159
         6.89777724e-01,   1.15719338e+00,   5.02387689e-01,
160
         1.65414778e+00,  -4.79422190e-02,   4.71465797e-01,
161
         4.71210862e-01,  -2.95445178e-01,  -9.27952481e-01,
162
        -2.84518822e-01,   4.50762651e-01,   3.57838417e-01,
163
         1.05556381e+00,  -1.25461973e+00,   5.25710748e-01,
164
         1.18346547e+00,  -6.36131832e-02,   1.99996624e+00,
165
        -4.05626343e-01,   5.02440229e-01,   3.06722159e-01,
166
         1.12961182e+00,   2.71252139e-01,   1.02751704e+00,
167
         6.58981355e-01,  -1.33754483e+00,  -1.88208047e+00,
168
         9.65909726e-02,   2.17877879e+00,   1.25656355e-01,
169
         1.97683689e+00,   1.88306505e+00,   3.93711759e-01,
170
         1.11480906e+00,   5.43163950e-02,  -9.70974509e-01,
171
         5.91343120e-01,   6.03472480e-01,  -1.41207708e-01,
172
        -3.57354046e-01,   8.83769732e-01,  -7.98277396e-01,
173
         5.34234315e-01,  -1.76017958e-01,  -6.70988950e-01,
174
        -9.92681894e-01,   1.02535613e+00,   7.86056043e-01,
175
         1.08465761e+00,   9.28624272e-01,  -1.29234470e-01,
176
        -8.71688683e-01,  -1.43193619e+00,  -9.92240568e-01,
177
         4.50317041e-01,  -7.83975597e-01,   3.25406806e-01,
178
         2.16974723e+00,  -8.98345345e-01,  -1.21821660e+00,
179
        -2.05393549e-01,  -6.97514681e-01,  -9.84930653e-01,
180
         2.92589293e-01,   1.75465316e+00,   2.89391096e-02,
181
        -5.70833465e-01,  -8.26878492e-01,   9.38516497e-02,
182
        -1.10404029e+00,   4.79417673e-01,   9.06859139e-01,
183
         2.84728627e-01,   7.81807537e-01,   5.94857977e-01,
184
        -2.39704052e+00,  -3.95317906e-01,   6.00154490e-01,
185
        -2.21365308e+00,   9.59143039e-01,   6.61087230e-01,
186
        -2.11076654e-01,  -6.53571930e-01,   2.17956383e+00,
187
         1.16704615e-01,   9.98712389e-01,  -1.62361914e+00,
188
        -2.50632371e-02,  -4.45459791e-01,  -2.28138155e-02,
189
        -3.59760026e-01,  -1.25357919e+00,   4.71340851e-02,
190
         1.40328071e+00,  -4.12591851e-01,   7.85809019e-01,
191
        -1.70616337e+00,   1.88482833e+00,   1.96424743e+00,
192
        -1.76543942e-01,  -3.80571853e-01,   6.87730233e-01,
193
        -1.71387963e-01,  -2.61269664e-01,   1.94983128e+00,
194
         7.46702909e-01,  -1.55802291e-01,   1.54348840e-01,
195
         4.84993880e-01,  -6.36064763e-01,  -7.77626949e-01,
196
         6.92906103e-01,   5.86780454e-01,  -1.71396865e+00,
197
         1.12970593e+00,  -7.31194601e-01,   1.44478155e+00,
198
         6.40973401e-01,  -3.27758206e-01,  -4.14741504e-01,
199
        -5.04916600e-01,  -9.43490941e-01,   1.74154128e+00,
200
        -7.45088483e-01,  -4.93447353e-02,  -5.05840112e-01,
201
         7.32234476e-01,   3.59136225e-02,   2.33032593e-01,
202
         6.78306052e-01,   5.33781323e-01,  -3.08066212e+00,
203
         5.36753627e-01,   2.21618896e+00,  -5.49002253e-01,
204
        -3.96205884e-02,   9.45672191e-01,   2.69695877e-02,
205
         1.86118132e-01,  -7.54374668e-02,  -6.00106159e-01,
206
         4.73807193e-02,   4.10719535e-02,  -2.88734543e-01,
207
        -1.52709149e+00,   8.63269201e-01,   7.52445801e-01,
208
         9.91226325e-01,  -1.65014451e-01,  -6.19173218e-01,
209
         1.24788844e+00,   1.98489106e+00,  -1.06515959e+00,
210
        -8.80476915e-01,   1.78981587e-01,   1.83692612e-01,
211
         1.53652830e+00,   5.00586066e-01,   2.78319035e-01,
212
         8.13336479e-01,  -8.53280967e-01,   6.95101671e-01,
213
        -7.84522637e-01,   6.21645705e-01,  -6.90717051e-01,
214
        -1.34331132e-02,  -4.63942849e-01,   8.46034390e-01,
215
         7.79139532e-01,   1.11506948e+00,  -7.58189523e-01,
216
         3.55010113e-01,   1.93401630e-02,   1.33945655e+00,
217
        -1.70378430e+00,   6.07595306e-01,   9.49078710e-01,
218
         1.65709736e+00,  -1.80847756e+00,   1.32234976e+00,
219
         2.31073785e+00,   2.47285661e-01,   4.83819946e-02,
220
         1.20939114e+00,   1.20967340e-01,   1.37374500e+00,
221
         4.33215652e-01,   5.92812032e-01,  -1.65824855e+00,
222
         7.62256866e-01,  -1.55651842e-01,   7.17398184e-01,
223
         9.81556110e-01,  -1.54787315e-01,  -1.20975829e+00,
224
         9.23432661e-01,   3.00827852e-01,  -6.14500486e-01,
225
        -3.26059019e-01,   1.41971663e+00,  -5.59087951e-01,
226
        -8.85611495e-01,  -3.77072359e-01,   1.90769576e+00,
227
        -1.27281422e+00,  -2.57577623e+00,  -1.29056980e+00,
228
         1.04105636e+00,   3.83955638e-01,  -2.41923810e-01,
229
         1.13747024e-01,   6.61993215e-01,   1.21725708e+00,
230
         5.53782077e-01,   5.93063386e-01,  -1.63011322e-01,
231
        -1.78736820e+00,   2.08120622e+00,  -3.66627082e-02,
232
         1.10356977e+00,  -3.66057113e-01,  -6.43033926e-01,
233
        -2.22016112e-02,   2.72905811e-01,  -2.67741983e-01,
234
         3.01415027e-01,   2.09089119e+00,   8.84618006e-01,
235
        -1.11558291e+00,   5.01184306e-01,   8.17462556e-01,
236
         1.23994641e+00,  -9.55828715e-01,   3.50830796e-01,
237
         1.13987551e+00,  -1.03647418e+00,  -3.39220874e-01,
238
        -1.21505253e+00,  -7.92370242e-01,  -3.92509918e-01,
239
        -3.54354051e-01,   7.32386956e-01,   1.49858239e+00,
240
        -1.40571944e+00,   9.71382936e-01,   1.84319717e-01,
241
        -2.62560983e+00,   3.15488537e-01,  -4.80518437e-01,
242
         8.72448418e-01,   6.51341675e-01,  -2.84050110e-02,
243
         3.51781188e-01,   7.02565779e-01,  -6.07502248e-01,
244
         6.52757394e-01,  -6.66621271e-01,   5.82922370e-02,
245
        -9.46398829e-01,  -6.71252481e-01,   1.33902920e+00,
246
         3.93403612e-02,  -1.52342841e+00,   9.93710825e-01,
247
        -2.86315569e-01,  -1.39171884e+00,   1.02611414e+00,
248
         2.18283569e+00,   1.42696284e+00,   5.15848836e-01,
249
         1.15392975e+00,  -5.34657374e-01,  -2.01754365e-01,
250
        -7.68709837e-01,   3.85433257e-01,  -6.97352436e-01,
251
         2.58712465e-01,  -2.49628821e-01,   1.84068402e-01,
252
        -6.25925483e-01,  -1.81143334e-01,   7.18039153e-01,
253
         5.59074589e-01,   6.65999999e-01,  -1.57075929e+00,
254
         5.58054042e-01,   7.44764249e-01,  -2.83785763e-01,
255
        -8.82562234e-02,   1.92806935e+00,  -9.68349222e-01,
256
         1.77906671e-01,  -8.25029579e-01,  -6.01310896e-01,
257
         1.95236866e-01,  -7.26205428e-01,  -6.06617076e-01,
258
        -1.66194008e-01,  -6.91522476e-01,   6.84314550e-01,
259
         5.83863823e-01,   4.93299245e-01,   9.82188985e-01,
260
         5.98147329e-01,  -5.18005846e-01,   1.58550046e-02,
261
         9.56595947e-03,  -2.45461199e-01,  -1.59207521e-01,
262
        -6.58198078e-01,  -2.13816850e+00,   1.59670116e+00,
263
        -6.09477093e-01,  -8.68643240e-02,  -4.41217685e-01,
264
        -4.11676773e-01,  -3.86013225e-01,  -3.92845894e-01,
265
        -2.52556017e+00,  -4.70652232e-01,   7.13473499e-01,
266
         1.94145904e-01,   7.56379495e-01,   4.09956072e-01,
267
         1.01246574e+00,  -5.18557610e-01,  -1.00192343e+00,
268
         4.41193746e-01,   2.82296893e-01,  -4.04582442e-01,
269
         1.71627030e-01,  -2.89539391e-01,   2.07682050e-03,
270
         1.04429805e+00,   5.40968294e-01,   1.34123694e+00,
271
        -2.80530112e+00,  -1.78870093e-02,  -5.97238191e-01,
272
         1.51157855e+00,  -7.27499261e-01,   9.12291671e-01,
273
        -5.35387214e-01,  -7.87289968e-01,  -1.82503774e-01,
274
         5.80673936e-01,   5.29634071e-01,  -6.96241271e-01,
275
        -1.56308494e+00,  -1.34181311e+00,   1.88487286e-01,
276
         1.40328626e+00,   6.00158404e-03,   6.55402421e-01,
277
        -1.61848068e-01,  -5.56679709e-01,  -2.26336297e-01,
278
        -5.73583832e-01,   1.96308115e+00,  -2.27547535e+00,
279
         8.43547860e-02,  -1.02630303e+00,  -7.40963015e-01,
280
        -3.29592672e-01,  -5.69506261e-01,   8.91549259e-01,
281
         3.67141173e-02,  -1.82231172e-01,  -9.51808458e-01,
282
        -4.75730687e-02,  -1.35256178e+00,   1.70960760e+00,
283
        -3.07172061e-01,   6.10801830e-01,   8.84296909e-01,
284
        -7.41061578e-01,   8.67690161e-01,   3.97588182e-01,
285
         8.21544341e-01,   3.30951455e-01,  -9.64367490e-01,
286
        -2.32152527e+00,   2.06939047e-01,   5.17611759e-02,
287
         2.22478518e+00,   4.40548750e-01,   1.39511688e-01,
288
         9.11680945e-01,  -1.12968322e+00,   9.10339662e-02,
289
        -9.90348342e-01,  -3.21560548e-01,  -1.33334300e+00,
290
        -1.01528637e+00,   3.44899432e-01,  -1.23835928e-01,
291
        -2.42770452e-02,  -9.05990669e-02,  -2.23922132e-01,
292
         7.47437385e-02,   7.53188446e-01,   1.82319928e+00,
293
        -2.66017608e-01,  -6.68749559e-02,   5.28398887e-02,
294
        -2.51901320e+00,   1.95600370e-01,  -4.77062768e-01,
295
         5.67450564e-01,  -7.38470031e-01,  -3.24464380e-01,
296
         3.63784870e-01,   3.75991861e-02,  -5.36347649e-01,
297
        -4.76756279e-01,   8.01781848e-01,   9.37678614e-01,
298
        -1.04848674e+00,  -1.19848372e+00,  -2.26439384e-01,
299
         1.36731011e+00,  -5.55136003e-01,  -2.60192909e+00,
300
        -1.54447063e-01,   1.96487305e+00,   1.35678183e-01,
301
        -1.67608204e+00,   1.12327576e+00,   5.81903509e-01,
302
         1.99026842e-01,   9.63293877e-01,   3.97108619e-01,
303
        -1.36076612e+00,  -3.22396458e-01,  -2.15067999e-01,
304
         6.18030436e-01,  -7.79655733e-03,   9.92891584e-01,
305
        -2.05604724e-03,  -8.96901674e-01,  -1.06635153e-01,
306
        -1.32070422e+00,  -7.53853714e-01,   5.09336526e-01,
307
         4.85341330e-01,   2.20445035e-01,  -1.78342545e-01,
308
         4.49018230e-02,  -3.36686870e-01,  -4.37369163e-02,
309
        -2.76415754e-02,  -9.74971071e-01,  -3.21277080e-01,
310
        -7.29857321e-01,  -2.71822112e+00,  -1.40805153e-01,
311
        -6.31972103e-01,  -1.18447030e+00,   4.70073687e-01,
312
         3.75218129e-01,   2.01854049e-02,   1.15084772e+00,
313
         1.37046917e+00,   2.19092559e-01,  -2.16799568e+00,
314
        -1.38993800e+00,  -1.46832196e+00,   6.74797051e-01,
315
        -2.23831431e+00,   7.86267279e-01,  -1.01850491e-02,
316
         5.23336585e-01,   5.73172679e-01,  -1.42427763e+00,
317
         9.78055988e-01,  -3.46729387e-01,  -4.18502508e-01,
318
        -7.61408845e-01,   1.00407787e-01,   9.71959636e-01,
319
         5.27960428e-01,  -1.36139193e+00,  -1.61909351e+00,
320
        -3.08090260e-01,  -7.25495879e-01,  -4.17010258e-01,
321
        -7.57455300e-01,  -9.88841992e-01,  -1.47721728e-01,
322
        -4.17639882e-02,   1.93209520e+00,  -2.90412408e-01,
323
         1.55586602e-01,   1.37128322e+00,   1.98776904e+00,
324
        -3.36005361e-01,   9.97719209e-01,   1.30942021e+00,
325
        -1.46843593e+00,   1.48923333e+00,  -9.11947452e-01,
326
        -1.17175494e+00,   6.09295874e-01,  -3.37116459e+00,
327
        -1.41109046e+00,   3.76436330e-01,   1.22230034e+00,
328
         3.13684661e-01,  -1.84230369e+00,   3.54782080e-01,
329
        -1.52693323e-01,  -1.82877549e+00,  -4.33652228e-01,
330
        -2.92262709e-01,  -4.26154081e-02,   1.20177625e+00,
331
         8.34324054e-01,   2.33224691e-01,  -4.94941496e-01,
332
        -1.30788518e+00,   5.31515478e-01,  -8.20831293e-01,
333
        -1.13579394e+00,   1.45329400e-01,  -5.20324531e-01,
334
         1.00047710e+00])
  • 偏度 skewnes
    概率分布的偏斜程度,我们需要做一个偏度检验。该检验有两个返回值,其中第二个返回值是p-value,即观察到的数据服从正态分布的概率,取值为0-1
    1
    stats.skewtest(generates)
    输出:
    1
    SkewtestResult(statistic=0.73500197175279103, pvalue=0.4623382932849327)
  • 峰度 kurtosis
    概率分布的陡峭程度。该检验和偏度检验类似。
    1
    stats.skewtest(generates)
    输出:
    1
    KurtosistestResult(statistic=0.45424860606802309, pvalue=0.64964990231896591)
  • 正态性检验 normality test
    检验数据服从正太分布的程度。
    1
    stats.normaltest(generates)
    输出:
    1
    NormaltestResult(statistic=5.2884112715980525, pvalue=0.07106178025936169)
    使用Scipy我们很方便的得到数据所在区域中某一百分比处的数值:
    例如:得到75%处的值:
    1
    stats.scoreatpercentile(generates,75)
    输出:
    1
    0.66404134087859246
    或者反过来,给定一个值,获取处在的百分位:
    1
    stats.percentileofscore(generates,0.66)
    输出:
    1
    74.8888888888889
    文到此处,可以用matplotlib库画个图看看了,关于matlotlib我单独出一篇笔记来记录。
    1
    import matplotlib.pyplot as plt
    2
    plt.hist(generates)
    3
    plt.show()
    输出图形:
    normaltest.png

先写到这儿,scipy分多篇来记录吧。

1 :老子《道德经》第十四章,老子故里,中国鹿邑。

“宠辱若惊,贵大患若身。
何谓宠辱若惊?
宠为下。
得之若惊,失之若惊,是谓宠辱若惊。
何谓贵大患若身?
吾所以有大患者,为吾有身。
及吾无身,吾有何患?
故贵以身为天下,若可以寄于天下,爱以身为天下者,若可托天下。”1

pandas

pandas是基于numpy构建的,让以 Numpy 为中心的应用变得更加简单。
pandas主要有Series(对映一维数组),DataFrame(对映二维数组),Panel(对映三维数组),Panel4D(对映四维数组),PanelND(多维)等数据结构。

  • Series
    一维数组,与Numpy中的一维array类似。二者与Python基本的数据结构List也很相近,其区别是:List中的元素可以是不同的数据类型,而Array和Series中则只允许存储相同的数据类型,这样可以更有效的使用内存,提高运算效率。
  • DataFrame
    二维的表格型数据结构。很多功能与R中的data.frame类似。可以将DataFrame理解为Series的容器。以下的内容主要以DataFrame为主。
  • Panel
    三维的数组,可以理解为DataFrame的容器。

导入包:

1
import numpy as np
2
import pandas as pd

Series

由一组数据(各种Numpy数据类型),以及一组与之相关的标签数据(即索引)组成。仅由一组数据即可产生最简单的Series,可以通过传递一个list对象来创建一个Series。

1
arr = pd.Series([1,3,4,5,6,7,0,4])
2
arr

输出:

1
0    1
2
1    3
3
2    4
4
3    5
5
4    6
6
5    7
7
6    0
8
7    4
9
dtype: int64

获取 Series 的索引:

1
arr.index

输出:

1
RangeIndex(start=0, stop=8, step=1)

DataFrame

DataFrame是一个表格型的数据结构,它含有一组有序的列,每一列的数据结构都是相同的,而不同的列之间则可以是不同的数据结构(数值、字符、布尔值等)。或者以数据库进行类比,DataFrame中的每一行是一个记录,名称为Index的一个元素,而每一列则为一个字段,是这个记录的一个属性。DataFrame既有行索引也有列索引,可以被看做由Series组成的字典(共用同一个索引)。
创建一个DataFrame,包括一个numpy array, 时间索引和列名字:

1
dates = pd.date_range('20180101',periods=6)
2
dates

输出:

1
DatetimeIndex(['2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04',
2
               '2018-01-05', '2018-01-06'],
3
              dtype='datetime64[ns]', freq='D')

创建DataFrame,如:

1
df = pd.DataFrame(np.random.randn(6,4),index=dates,columns=list('ABCD'))
2
df

np.random.randn(6,4) 从标准正态分布中创建6行4列的二维矩阵

输出:

1
	        A	        B	        C	        D
2
2018-01-01	-0.538987	-1.173826	1.607785	-1.168397
3
2018-01-02	-0.987674	-0.961643	-0.636837	-0.607176
4
2018-01-03	-1.065446	0.686846	-0.241674	0.296789
5
2018-01-04	0.338885	0.459906	0.852208	1.007623
6
2018-01-05	-0.227588	0.872227	2.077327	0.886460
7
2018-01-06	-0.838204	0.087443	0.537748	1.372528

通过传递一个能够被转换成类似序列结构的字典对象来创建一个DataFrame:

1
df1 = pd.DataFrame({'A':3.,
2
                  'B':pd.date_range('20180101',periods=6),
3
                  'C':np.array([2]*6,dtype='int32'),
4
                  'D':pd.Series(2,index=list(range(6)),dtype='float32')
5
                   })
6
df1

输出:

1
2
    A	B	        C	D
3
0	3.0	2018-01-01	2	2.0
4
1	3.0	2018-01-02	2	2.0
5
2	3.0	2018-01-03	2	2.0
6
3	3.0	2018-01-04	2	2.0
7
4	3.0	2018-01-05	2	2.0
8
5	3.0	2018-01-06	2	2.0

查看不同列的数据类型:

1
df1.dtypes

输出:

1
A           float64
2
B    datetime64[ns]
3
C             int32
4
D           float32
5
dtype: object

DataFrame查看数据

以df为数据蓝本,查看前2条记录:

1
df.head(2)

输出:

1
	        A	        B	        C	        D
2
2018-01-01	-0.538987	-1.173826	1.607785	-1.168397
3
2018-01-02	-0.987674	-0.961643	-0.636837	-0.607176

查看后2条记录:

1
df.tail(2)

输出:

1
	        A	        B	        C	        D
2
2018-01-05	-0.227588	0.872227	2.077327	0.886460
3
2018-01-06	-0.838204	0.087443	0.537748	1.372528

显示索引、列和底层的numpy数据:

1
df.index

输出:

1
DatetimeIndex(['2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04',
2
               '2018-01-05', '2018-01-06'],
3
              dtype='datetime64[ns]', freq='D')

查看 DataFrame 的列名

1
df.columns

输出:

1
Index(['A', 'B', 'C', 'D'], dtype='object')

查看 DataFrame 的值:

1
df.values

输出:

1
array([[-0.53898743, -1.17382617,  1.60778544, -1.16839686],
2
       [-0.98767434, -0.96164339, -0.63683738, -0.60717624],
3
       [-1.06544554,  0.68684576, -0.24167378,  0.29678857],
4
       [ 0.33888503,  0.45990635,  0.85220803,  1.0076235 ],
5
       [-0.22758765,  0.87222716,  2.07732729,  0.88645989],
6
       [-0.83820381,  0.08744284,  0.53774757,  1.37252846]])

describe()函数对于数据的快速统计汇总:

1
df.describe()

输出:

1
	   A	    B	        C	         D
2
count	6.000000	6.000000	6.000000	6.000000
3
mean	-0.553169	-0.004841	0.699426	0.297971
4
std	0.535618	0.866508	1.043502	0.997409
5
min	-1.065446	-1.173826	-0.636837	-1.168397
6
25%	-0.950307	-0.699372	-0.046818	-0.381185
7
50%	-0.688596	0.273675	0.694978	0.591624
8
75%	-0.305438	0.630111	1.418891	0.977333
9
max	0.338885	0.872227	2.077327	1.372528

对结果简单解释一下:

count:数量
mean:平均值
std:标准偏差
min:最小值
max:最大值

其中25% 50% 75% 四分位数;即把数值由小到大排列并分成四等份,处于三个分割点位置的数值就是四分位数。
第1四分位数 (Q1),又称“较小四分位数”,等于该样本中所有数值由小到大排列后第25%的数字。
第2四分位数 (Q2),又称“中位数”,等于该样本中所有数值由小到大排列后第50%的数字。
第3四分位数 (Q3),又称“较大四分位数”,等于该样本中所有数值由小到大排列后第75%的数字。
第3四分位数与第1四分位数的差距又称四分位距(InterQuartile Range,IQR)

转置:df.transpose() or .T

1
df.transpose() or df.T

输出:

1
	2018-01-01 00:00:00	2018-01-02 00:00:00	2018-01-03 00:00:00	2018-01-04 00:00:00	2018-01-05 00:00:00	2018-01-06 00:00:00
2
A	-0.538987	-0.987674	-1.065446	0.338885	-0.227588	-0.838204
3
B	-1.173826	-0.961643	0.686846	0.459906	0.872227	0.087443
4
C	1.607785	-0.636837	-0.241674	0.852208	2.077327	0.537748
5
D	-1.168397	-0.607176	0.296789	1.007623	0.886460	1.372528

按值进行排序

1
df.sort_values(by='A',ascending=False)

输出:

1
	        A	        B	        C	        D
2
2018-01-04	0.338885	0.459906	0.852208	1.007623
3
2018-01-05	-0.227588	0.872227	2.077327	0.886460
4
2018-01-01	-0.538987	-1.173826	1.607785	-1.168397
5
2018-01-06	-0.838204	0.087443	0.537748	1.372528
6
2018-01-02	-0.987674	-0.961643	-0.636837	-0.607176
7
2018-01-03	-1.065446	0.686846	-0.241674	0.296789

获取数据

  • 按列获取数据
    1
    df['A']
    输出:
    1
    2018-01-01   -0.538987
    2
    2018-01-02   -0.987674
    3
    2018-01-03   -1.065446
    4
    2018-01-04    0.338885
    5
    2018-01-05   -0.227588
    6
    2018-01-06   -0.838204
    7
    Freq: D, Name: A, dtype: float64
    按列取多列
    1
    df[['A','B']]
    输出:
    1
    	        A	        B
    2
    2018-01-01	-0.538987	-1.173826
    3
    2018-01-02	-0.987674	-0.961643
    4
    2018-01-03	-1.065446	0.686846
    5
    2018-01-04	0.338885	0.459906
    6
    2018-01-05	-0.227588	0.872227
    7
    2018-01-06	-0.838204	0.087443
  • 按行获取数据
    1
    df[:3]
    输出:
    1
    	        A	        B	        C	        D
    2
    2018-01-01	-0.538987	-1.173826	1.607785	-1.168397
    3
    2018-01-02	-0.987674	-0.961643	-0.636837	-0.607176
    4
    2018-01-03	-1.065446	0.686846	-0.241674	0.296789

    貌似等效于df.head(3)

.ix(位置or标签起,位置or标签止)来获取数据,它自动根据给到的索引类型判断是使用位置还是标签进行切片。

1
df.ix['2018-01-01':'2018-01-02']

输出:

1
	        A	        B	        C	        D
2
2018-01-01	-0.538987	-1.173826	1.607785	-1.168397
3
2018-01-02	-0.987674	-0.961643	-0.636837	-0.607176
1
df.ix[1,1]

输出:

1
-0.96164339276293087
1
df.ix[1,'C']

输出:

1
-0.63683738086017361

通过逻辑指针进行数据切片:

df[逻辑条件]
df[df.xxx >= 2] #单个逻辑条件
df[(df.xxx >=1 ) & (df.xxx < 3) ] #多个逻辑条件组合

1
df[df.A>0]

输出:

1
2
            A	        B	        C	        D
3
2018-01-04	0.338885	0.459906	0.852208	1.007623

可以利用逻辑条件进行更改数据

panel (略)

略…..

缺失数据处理

去掉包含缺失值的行

  • df.dropna()
    将有缺失数据行丢弃
  • df.fillna(value=0)
    将缺失项赋值0
  • df.isnull(df)
    判断数据是否为nan,并进行布尔填充

函数的应用和映射

列计算平均值

1
df.mean()

输出:

1
A   -0.553169
2
B   -0.004841
3
C    0.699426
4
D    0.297971
5
dtype: float64

行计算平均值

1
df.mean(1)

输出:

1
2018-01-01   -0.318356
2
2018-01-02   -0.798333
3
2018-01-03   -0.080871
4
2018-01-04    0.664656
5
2018-01-05    0.902107
6
2018-01-06    0.289879
7
Freq: D, dtype: float64

罗列出其他常用的方法:

1
count 非na值的数量
2
3
describe 针对Series或个DataFrame列计算汇总统计
4
5
min、max 计算最小值和最大值
6
7
argmin、argmax 计算能够获取到最大值和最小值得索引位置(整数)
8
9
idxmin、idxmax 计算能够获取到最大值和最小值得索引值
10
11
quantile 计算样本的分位数(01
12
13
sum 值的总和
14
15
mean 值得平均数
16
17
median 值得算术中位数(50%分位数)
18
19
mad 根据平均值计算平均绝对离差
20
21
var 样本值的方差
22
23
std 样本值的标准差
24
25
skew 样本值得偏度(三阶矩)
26
27
kurt 样本值得峰度(四阶矩)
28
29
cumsum 样本值得累计和
30
31
cummin,cummax 样本值得累计最大值和累计最小值
32
33
cumprod 样本值得累计积
34
35
diff 计算一阶差分(对时间序列很有用)
36
37
pct_change 计算百分数变化

数据规整

Pandas提供了大量的方法能够轻松的对Series,DataFrame和Panel对象进行各种符合各种逻辑关系的合并操作

  • concat 可以沿一条轴将多个对象堆叠到一起。
  • append 将一行连接到一个DataFrame上
  • duplicated 移除重复数据

1:老子《道德经》第十三章,老子故里,中国鹿邑。