【机器学习】pyspark中RDD的若干操作

来源:互联网 发布:淘宝网天猫中老年女鞋 编辑:程序博客网 时间:2024/06/12 04:09

1,读取文件

from pyspark import SparkContextsc = SparkContext('local', 'pyspark')

a,text = sc.textFile(“file:///d:/test.txt”)
b,rdd = sc.parallelize([1,2,3,4,5])

2,RDD的操作
大家还对python的list comprehension有印象吗,RDDs可以进行一系列的变换得到新的RDD,有点类似那个过程,我们先给大家提一下RDD上最最常用到的transformation:

  • map() 对RDD的每一个item都执行同一个操作
  • flatMap() 对RDD中的item执行同一个操作以后得到一个list,然后以平铺的方式把这些list里所有的结果组成新的list
  • filter() 筛选出来满足条件的item distinct() 对RDD中的item去重
  • sample() 从RDD中的item中采样一部分出来,有放回或者无放回
  • sortBy() 对RDD中的item进行排序
    如果你想看操作后的结果,可以用一个叫做collect()的action把所有的item转成一个Python list。
    一个简单的例子
numbersRDD = sc.parallelize(range(1,10+1))print(numbersRDD.collect())squaresRDD = numbersRDD.map(lambda x: x**2)  # Square every numberprint(squaresRDD.collect())filteredRDD = numbersRDD.filter(lambda x: x % 2 == 0)  # Only the evens

结果

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10][1, 4, 9, 16, 25, 36, 49, 64, 81, 100][2, 4, 6, 8, 10]

flatMap()与Map()的关系相当于,Python中list的extend和append的关系。

前面提到的Transformation,可以一个接一个地串联,比如:

def doubleIfOdd(x):    if x % 2 == 1:        return 2 * x    else:        return xresultRDD = (numbersRDD           # In parentheses so we can write each             .map(doubleIfOdd)    # transformation in one line             .filter(lambda x: x > 6)             .distinct())resultRDD.collect()

结果:

[8, 10, 18, 14]

3,RDD间的操作
如果你手头上有2个RDD了,下面的这些操作能够帮你对他们以个种方式组合得到1个RDD:

  • rdd1.union(rdd2): 所有rdd1和rdd2中的item组合
  • rdd1.intersection(rdd2): rdd1 和 rdd2的交集
  • rdd1.substract(rdd2): 所有在rdd1中但不在rdd2中的item(差集)
  • rdd1.cartesian(rdd2): rdd1 和 rdd2中所有的元素笛卡尔乘积
    如下:
numbersRDD = sc.parallelize([1,2,3])moreNumbersRDD = sc.parallelize([2,3,4])numbersRDD.union(moreNumbersRDD).collect()

结果:

[1, 2, 3, 2, 3, 4]

特别注意:Spark的一个核心概念是惰性计算。当你把一个RDD转换成另一个的时候,这个转换不会立即生效执行!!!
Spark会把它先记在心里,等到真的需要拿到转换结果的时候,才会重新组织你的transformations(因为可能有一连串的变换)
这样可以避免不必要的中间结果存储和通信。
刚才提到了惰性计算,那么什么东西能让它真的执行转换与运算呢? 是的,就是我们马上提到的Actions,下面是常见的action,当他们出现的时候,表明我们需要执行刚才定义的transform了:

  • collect(): 计算所有的items并返回所有的结果到driver端,接着 collect()会以Python list的形式返回结果
  • first(): 和上面是类似的,不过只返回第1个item
  • take(n): 类似,但是返回n个item
  • count(): 计算RDD中item的个数
  • top(n): 返回头n个items,按照自然结果排序
  • reduce(): 对RDD中的items做聚合
    reduce的例子:
rdd = sc.parallelize(range(1,10+1))rdd.reduce(lambda x, y: x + y)

结果:

55

5,针对更复杂结构的transform和action
有时候我们会遇到更复杂的结构,比如非常非常经典的是以元组形式组织的k-v对(key, value)我们把它叫做pair RDDs,而Sark中针对这种item结构的数据,定义了一些transform和action:

  • reduceByKey(): 对所有有着相同key的items执行reduce操作
  • groupByKey(): 返回类似(key, listOfValues)元组的RDD,后面的value List 是同一个key下面的
  • sortByKey(): 按照key排序
  • countByKey(): 按照key去对item个数进行统计
  • collectAsMap(): 和collect有些类似,但是返回的是k-v的字典
    简单的词频统计的例子:
rdd = sc.parallelize(["Hello hello", "Hello New York", "York says hello"])resultRDD = (    rdd    .flatMap(lambda sentence: sentence.split(" "))  # split into words    .map(lambda word: word.lower())                 # lowercase    .map(lambda word: (word, 1))                    # count each appearance    .reduceByKey(lambda x, y: x + y)                # add counts for each word)resultRDD.collect()

结果:

[('says', 1), ('new', 1), ('hello', 4), ('york', 2)]

若将结果以k-v字典的形式返回:

result = resultRDD.collectAsMap()

结果:

{'hello': 4, 'new': 1, 'says': 1, 'york': 2}

如果你想要出现频次最高的2个词,可以这么做:

print(resultRDD      .sortBy(keyfunc=lambda (word, count): count, ascending=False)      .take(2))

结果:

[('hello', 4), ('york', 2)]

6,在给定2个RDD后,我们可以通过一个类似SQL的方式去join他们
如:

homesRDD = sc.parallelize([        ('Brussels', 'John'),        ('Brussels', 'Jack'),        ('Leuven', 'Jane'),        ('Antwerp', 'Jill'),    ])# Quality of life index for various citieslifeQualityRDD = sc.parallelize([        ('Brussels', 10),        ('Antwerp', 7),        ('RestOfFlanders', 5),    ])
homesRDD.join(lifeQualityRDD).collect()

结果为:

[('Antwerp', ('Jill', 7)), ('Brussels', ('John', 10)), ('Brussels', ('Jack', 10))]
homesRDD.leftOuterJoin(lifeQualityRDD).collect()

结果为:

[('Antwerp', ('Jill', 7)), ('Brussels', ('John', 10)), ('Brussels', ('Jack', 10)), ('Leuven', ('Jane', None))]
原创粉丝点击