转:https://blog.csdn.net/weimingyu945/article/details/77981884

感谢!

-------------------------------------------------------------------------------------------------------

基本操作:

 
运行时获取spark版本号(以spark 2.0.0为例):
sparksn = SparkSession.builder.appName("PythonSQL").getOrCreate()

print sparksn.version
 
 
创建和转换格式:
 
Pandas和Spark的DataFrame两者互相转换:
pandas_df = spark_df.toPandas() spark_df = sqlContext.createDataFrame(pandas_df)
 
与Spark RDD的相互转换:
rdd_df = df.rdd df = rdd_df.toDF()
注:rdd转df前提是每个rdd的类型都是Row类型
 
 
增:
 
新增列:
df.withColumn(“xx”, 0).show() 会报错,因为原来没有xx列

from pyspark.sql import functions
df = df.withColumn(“xx”, functions.lit(0)).show()
 
fillna函数:
df.na.fill()
 
以原有列为基础添加列:
df = df.withColumn('count20', df["count"] - 20)  # 新列为原有列的数据减去20
 
删:
 
删除一列:
df.drop('age').collect()

df.drop(df.age).collect()
 
dropna函数:
df = df.na.drop()  # 扔掉任何列包含na的行
df = df.dropna(subset=['col_name1', 'col_name2'])  # 扔掉col1或col2中任一一列包含na的行
 
 
改:
 
修改原有df[“xx”]列的所有值:
df = df.withColumn(“xx”, 1)
 
修改列的类型(类型投射):
df = df.withColumn("year2", df["year1"].cast("Int"))
 
合并2个表的join方法:
 df_join = df_left.join(df_right, df_left.key == df_right.key, "inner")
其中,方法可以为:`inner`, `outer`, `left_outer`, `right_outer`, `leftsemi`.
 
groupBy方法整合:
GroupedData = df.groupBy(“age”)

应用单个函数(按照A列同名的进行分组,组内对B列进行均值计算来合并):

df.groupBy(“A”).avg(“B”).show()
 
应用多个函数:
from pyspark.sql import functions
df.groupBy(“A”).agg(functions.avg(“B”), functions.min(“B”), functions.max(“B”)).show()
整合后GroupedData类型可用的方法(均返回DataFrame类型):
avg(*cols)     ——   计算每组中一列或多列的平均值
count()          ——   计算每组中一共有多少行,返回DataFrame有2列,一列为分组的组名,另一列为行总数
max(*cols)    ——   计算每组中一列或多列的最大值
mean(*cols)  ——  计算每组中一列或多列的平均值
min(*cols)     ——  计算每组中一列或多列的最小值
sum(*cols)    ——   计算每组中一列或多列的总和
 
【函数应用】将df的每一列应用函数f:
df.foreach(f) 或者 df.rdd.foreach(f)
 
【函数应用】将df的每一块应用函数f:
df.foreachPartition(f) 或者 df.rdd.foreachPartition(f)
 
【Map和Reduce应用】返回类型seqRDDs
df.map(func)
df.reduce(func)
 
解决toDF()跑出First 100 rows类型无法确定的异常,可以采用将Row内每个元素都统一转格式,或者判断格式处理的方法,解决包含None类型时转换成DataFrame出错的问题:
    @staticmethod

    def map_convert_none_to_str(row):
        dict_row = row.asDict()
 
        for key in dict_row:
            if key != 'some_column_name':
                value = dict_row[key]
                if value is None:
                    value_in = str("")
                else:
                    value_in = str(value)
                dict_row[key] = value_in
 
        columns = dict_row.keys()
        v = dict_row.values()
        row = Row(*columns)
        return row(*v)
 
 
查:
行元素查询操作:
像SQL那样打印列表前20元素(show函数内可用int类型指定要打印的行数):
df.show()
df.show(30)
 
以树的形式打印概要
df.printSchema()
 
获取头几行到本地:
list = df.head(3)   # Example: [Row(a=1, b=1), Row(a=2, b=2), ... ...]
list = df.take(5)   # Example: [Row(a=1, b=1), Row(a=2, b=2), ... ...]
 
输出list类型,list中每个元素是Row类:
list = df.collect()
注:此方法将所有数据全部导入到本地
 
查询总行数:
 int_num = df.count()
 
查询某列为null的行:
from pyspark.sql.functions import isnull
df = df.filter(isnull("col_a"))
 
 
列元素操作:
获取Row元素的所有列名:
r = Row(age=11, name='Alice')
print r.__fields__    #  ['age', 'name']
 
选择一列或多列:
df.select(“name”)
df.select(df[‘name’], df[‘age’]+1)
df.select(df.a, df.b, df.c)    # 选择a、b、c三列
df.select(df["a"], df["b"], df["c"])    # 选择a、b、c三列
 
排序:
df = df.sort("age", ascending=False)
 
过滤数据(filter和where方法相同):
df = df.filter(df['age']>21)
df = df.where(df['age']>21)

# 对null或nan数据进行过滤:
from pyspark.sql.functions import isnan, isnull
df = df.filter(isnull("a"))  # 把a列里面数据为null的筛选出来(代表python的None类型)
df = df.filter(isnan("a"))  # 把a列里面数据为nan的筛选出来(Not a Number,非数字数据)

 
 
SQL操作:
DataFrame注册成SQL的表:
df.createOrReplaceTempView("TBL1")
 
进行SQL查询(返回DataFrame):
conf = SparkConf()
ss = SparkSession.builder.appName("APP_NAME").config(conf=conf).getOrCreate()

df = ss.sql(“SELECT name, age FROM TBL1 WHERE age >= 13 AND age <= 19″)

 
 
 
时间序列操作:
 
先按某几列分组,再按时间段分组:
from pyspark.sql.functions import window

win_monday = window("col1", "1 week", startTime="4 day")
GroupedData = df.groupBy([df.col2, df.col3, df.col4, win_monday])
 
 
 
 
参考资料:
传统MySQL查询(执行时间 19 min 16.58 sec):
mysql>

 
SELECT
    MIN(yearD),
    MAX(yearD) AS max_year,
    Carrier,
    COUNT(*) AS cnt,
    SUM(IF(ArrDelayMinutes > 30, 1, 0)) AS flights_delayed,
    ROUND(SUM(IF(ArrDelayMinutes > 30, 1, 0)) / COUNT(*),2) AS rate
FROM
    ontime_part
WHERE
    DayOfWeek NOT IN (6 , 7)
        AND OriginState NOT IN ('AK' , 'HI', 'PR', 'VI')
        AND DestState NOT IN ('AK' , 'HI', 'PR', 'VI')
GROUP BY carrier
HAVING cnt > 1000 AND max_year > '1990'
ORDER BY rate DESC , cnt DESC
LIMIT 10;
 
使用Scala语言摘写的Spark查询(执行时间 2 min 19.628 sec):
scala>

val jdbcDF = spark.read.format("jdbc").options(Map("url" ->  "jdbc:mysql://localhost:3306/ontime?user=root&password=mysql",
                                                   "dbtable" -> "ontime.ontime_sm",     
                                                   "fetchSize" -> "10000",
                                                   "partitionColumn" -> "yeard",
                                                   "lowerBound" -> "1988",
                                                   "upperBound" -> "2015",
                                                   "numPartitions" -> "48")).load()
jdbcDF.createOrReplaceTempView("ontime")
val sqlDF = sql("SELECT
                     MIN(yearD),
                     MAX(yearD) AS max_year,
                     Carrier,
                     COUNT(*) AS cnt,
                     SUM(IF(ArrDelayMinutes > 30, 1, 0)) AS flights_delayed,
                     ROUND(SUM(IF(ArrDelayMinutes > 30, 1, 0)) / COUNT(*),2) AS rate
                 FROM
                     ontime_part
                 WHERE
                     DayOfWeek NOT IN (6 , 7)
                         AND OriginState NOT IN ('AK' , 'HI', 'PR', 'VI')
                         AND DestState NOT IN ('AK' , 'HI', 'PR', 'VI')
                 GROUP BY carrier
                 HAVING cnt > 1000 AND max_year > '1990'
                 ORDER BY rate DESC , cnt DESC
                 LIMIT 10;
")
sqlDF.show()
 
 
Spark RDD中的map、reduce等操作的概念详解:
 
map将RDD中的每个元素都经过map内函数处理后返回给原来的RDD,即对每个RDD单独处理且不影响其它和总量。属于一对一的关系(这里一指的是对1个RDD而言)。
 
flatMap将RDD中的每个元素进行处理,返回一个list,list里面可以是1个或多个RDD,最终RDD总数会不变或变多。属于一变多的关系(这里一指的是对1个RDD而言)。
 
reduce将RDD中元素前两个传给输入函数,产生一个新的return值,新产生的return值与RDD中下一个元素(第三个元素)组成两个元素,再被传给输入函数,直到最后只有一个值为止。属于多变一的关系。
val c = sc.parallelize(1 to 10)
c.reduce((x, y) => x + y)//结果55
 
reduceByKey(binary_function) 
reduceByKey就是对元素为KV对的RDD中Key相同的元素的Value进行binary_function的reduce操作,因此,Key相同的多个元素的值被reduce为一个值,然后与原RDD中的Key组成一个新的KV对。属于多变少的关系。
val a = sc.parallelize(List((1,2),(1,3),(3,4),(3,6)))
a.reduceByKey((x,y) => x + y).collect

PySpark的DataFrame处理方法的更多相关文章

  1. Python DataFrame to_sql方法插入日期或时间类型的数据时 报ORA-01861 文字与字符串不匹配 的解决方法

    业务团队近期提出一个需求: 希望在接口调用之前先批量插入Excel中的数据作为数据预置 这个需求以前已经开发完成 本来以为可以很快调试完毕 没成想遭遇一个难关 DataFrame.to_sql方法在执 ...

  2. python pandas dataframe to_sql方法error及其解决

    今天遇到了一个问题,很是奇怪,自己也想了一个另类的方法将其解决了,现在将详细过程经过记录如下: 我在处理完一个dataframe之后,需要将其写回到数据库.这个dataframe比较大,共有53列,7 ...

  3. python pandas ---Series,DataFrame 创建方法,操作运算操作(赋值,sort,get,del,pop,insert,+,-,*,/)

    pandas 是基于 Numpy 构建的含有更高级数据结构和工具的数据分析包 pandas 也是围绕着 Series 和 DataFrame 两个核心数据结构展开的, 导入如下: from panda ...

  4. pyspark使用-dataframe操作

    一.读取csv文件 1.用pandas读取 import pandas as pd from pyspark.sql import SparkSession spark=SparkSession.bu ...

  5. 【转载】Spark SQL 1.3.0 DataFrame介绍、使用

    http://www.aboutyun.com/forum.php?mod=viewthread&tid=12358&page=1 1.DataFrame是什么?2.如何创建DataF ...

  6. 《Spark Python API 官方文档中文版》 之 pyspark.sql (一)

    摘要:在Spark开发中,由于需要用Python实现,发现API与Scala的略有不同,而Python API的中文资料相对很少.每次去查英文版API的说明相对比较慢,还是中文版比较容易get到所需, ...

  7. 《Spark Python API 官方文档中文版》 之 pyspark.sql (二)

    摘要:在Spark开发中,由于需要用Python实现,发现API与Scala的略有不同,而Python API的中文资料相对很少.每次去查英文版API的说明相对比较慢,还是中文版比较容易get到所需, ...

  8. Spark核心类:SQLContext和DataFrame

    http://blog.csdn.net/pipisorry/article/details/53320669 pyspark.sql.SQLContext Main entry point for ...

  9. 《Spark Python API 官方文档中文版》 之 pyspark.sql (四)

    摘要:在Spark开发中,由于需要用Python实现,发现API与Scala的略有不同,而Python API的中文资料相对很少.每次去查英文版API的说明相对比较慢,还是中文版比较容易get到所需, ...

随机推荐

  1. 【微信小程序】view顶部固定或底部固定 + scroll-view中的元素view也可以使用position:fixed;固定选中元素位置

    1.顶端固定核心代码如下: <view class="page__hd" style="position:fixed; top:0;width: 750rpx;&q ...

  2. 如何将Emmet安装到Notepad++?

    1.下载Notepad++插件;(zen-Coding for Notepad++)2.解压后将压缩包中的文件放入Notepad++安装目录下的plugins文件夹中;3.重新启动就能看到菜单栏上增加 ...

  3. ORACLE 查看CPU使用率最高的语句及一些性能查询语句

    select * from (select sql_text,sql_id,cpu_time from v$sql order by cpu_time desc) where rownum<=1 ...

  4. Java程序猿笔试面试之String4

    怎样删除String中反复的字符good? 思想一:蛮力法,进行双重循环,此算法的复杂度为O(n^2),n是指字符串的长度 public class RemoveSameChar { public s ...

  5. C#方法中的ref和out

    ref        通常我们向方法中传递的是值.方法获得的是这些值的一个拷贝,然后使用这些拷贝,当方法运行完毕后,这些拷贝将被丢弃,而原来的值不将受到影响.此外我们还有其他向方法传递参数的形式,引用 ...

  6. Vue组件开发实践之scopedSlot的传递

    收录待用,修改转载已取得腾讯云授权 导语 现今的前端开发都讲究模块化组件化,即把公共的交互和功能封装到一个个的组件之中,在开发整体界面的时候就能像搭积木一样快速清晰高效.在使用Vue开发我们的vhtm ...

  7. 转:sublime2 官方网址

    1. sublime2 官方网址 http://www.sublimetext.com/2

  8. 谋哥:《App自推广》开篇之回到远古人类

    [谋哥每天一干货.第六十八篇] 这两天帮谋天团的杨整体验他的App--"闪聊"的内測新版,改版后这款App命名为"美丫",一款致力于打造国内首款专注于女性社交的 ...

  9. angularjs中的$eval方法

    在controller中定义了一个变量 $scope.a_1 = "abc"; 想在view里面动态输出,因为这个数字是动态的,这么输出肯定是不行的{{'a_' + '1'}},因 ...

  10. onvif获取摄像头的流媒体地址完整流程

    linux设备上的Onvif 实现6:获取摄像头的流媒体地址完整流程 整体流程: Probe: 发现网络摄像头,获取webserver地址 http://192.168.15.240/onvif/de ...