Python 在pyspark中不使用pivot的情况下创建groupby的有效方法
我有一个查询,需要使用pyspark计算内存利用率。我使用pivot通过python pandas实现了这一点,但现在我需要在pyspark中实现,并且pivoting将是一个昂贵的函数,因此我想知道pyspark中是否有其他解决方案Python 在pyspark中不使用pivot的情况下创建groupby的有效方法,python,apache-spark,pyspark,apache-spark-sql,pyspark-sql,Python,Apache Spark,Pyspark,Apache Spark Sql,Pyspark Sql,我有一个查询,需要使用pyspark计算内存利用率。我使用pivot通过python pandas实现了这一点,但现在我需要在pyspark中实现,并且pivoting将是一个昂贵的函数,因此我想知道pyspark中是否有其他解决方案 time_stamp Hostname kpi kpi_subtype value_current 2019/08/17 10:01:05 Server1 memory Total 100 2019/08/17 10:
time_stamp Hostname kpi kpi_subtype value_current
2019/08/17 10:01:05 Server1 memory Total 100
2019/08/17 10:01:06 Server1 memory used 35
2019/08/17 10:01:09 Server1 memory buffer 8
2019/08/17 10:02:04 Server1 memory cached 10
2019/08/17 10:01:05 Server2 memory Total 100
2019/08/17 10:01:06 Server2 memory used 42
2019/08/17 10:01:09 Server2 memory buffer 7
2019/08/17 10:02:04 Server2 memory cached 9
2019/08/17 10:07:05 Server1 memory Total 100
2019/08/17 10:07:06 Server1 memory used 35
2019/08/17 10:07:09 Server1 memory buffer 8
2019/08/17 10:07:04 Server1 memory cached 10
2019/08/17 10:08:05 Server2 memory Total 100
2019/08/17 10:08:06 Server2 memory used 35
2019/08/17 10:08:09 Server2 memory buffer 8
2019/08/17 10:08:04 Server2 memory cached 10
需要转化为
time_stamp Hostname kpi Percentage
2019-08-17 10:05:00 Server1 memory 17
2019-08-17 10:05:00 Server2 memory 26
2019-08-17 10:10:00 Server1 memory 17
2019-08-17 10:10:00 Server2 memory 17
我使用的Python代码
df3 = pd.read_csv('/home/yasin/Documents/IMI/Data/memorry sample.csv')
df3['time_stamp'] = pd.to_datetime(df3['time_stamp'])
ns5min=5*60*1000000000
df3['time_stamp'] = pd.to_datetime(((df3['time_stamp'].astype(np.int64) // ns5min + 1 ) * ns5min))
df4 = df3.pivot_table('value_current' , ['time_stamp' , 'Hostname ' , 'kpi' ], 'kpi_subtype')
df4 = df4.reset_index()
df4['Percentage'] = ((df4['Total'] - (df4['Total'] - df4['used'] + df4['buffer'] + df4['cached'])) / df4['Total']) * 100
在pyspark中寻找一种复制方法以及在python中寻找一种更有效的方法作为pivot是一项昂贵的操作,我需要在一个非常大的数据集上每5分钟执行一次,当转换为列的值列表未知时,Pivoting是昂贵的。Spark有一个重载的
pivot
方法,将它们作为参数
def pivot(pivotColumn: String, values: Seq[Any])
如果它们未知,Spark必须从数据集中排序和收集不同的值。否则,逻辑就相当简单,并且描述得很好
该实现添加了一个新的逻辑运算符(o.a.s.sql.catalyst.plans.logical.Pivot)。该逻辑运算符由新的analyzer规则(o.a.s.sql.catalyst.analysis.analyzer.ResolvePivot)转换,该规则当前将其转换为包含大量if语句的聚合,每个pivot值一个表达式
例如,df.groupBy(“A”,“B”).pivot(“C”,Seq(“small”,“large”).sum(“D”)将被转换为df.groupBy(“A”,“B”).agg(expr(“sum”(如果(C='small',D,null)))的等价物,expr(“sum”(如果(C='large',D,null)))。您可以自己做这件事,但它会变得很长,而且可能很快就会出错
如果不旋转,我会这样做:
val in = spark.read.csv("input.csv")
//cast to the unix timestamp
.withColumn("timestamp", unix_timestamp($"time_stamp", "yyyy/MM/dd HH:mm:ss").cast(TimestampType))
.drop($"time_stamp")
现在,我们可以按时间窗口将数据集与主机名分组,并将KPI指标收集到映射中。这是一个很好的描述
val joinMap = udf { values: Seq[Map[String, Double]] => values.flatten.toMap }
val grouped = in.groupBy(window($"timestamp", "5 minutes"), $"Hostname")
.agg(joinMap(collect_list(map($"kpi_subtype", $"value_current".cast(DoubleType)))).as("metrics"))
输出
+------------------------------------------+--------+-------------------------------------------------------------+
|window |Hostname|metrics |
+------------------------------------------+--------+-------------------------------------------------------------+
|[2019-08-17 10:00:00, 2019-08-17 10:05:00]|Server1 |[Total -> 100.0, used -> 35.0, buffer -> 8.0, cached -> 10.0]|
|[2019-08-17 10:00:00, 2019-08-17 10:05:00]|Server2 |[Total -> 100.0, used -> 42.0, buffer -> 7.0, cached -> 9.0] |
|[2019-08-17 10:05:00, 2019-08-17 10:10:00]|Server1 |[Total -> 100.0, used -> 35.0, buffer -> 8.0, cached -> 10.0]|
|[2019-08-17 10:05:00, 2019-08-17 10:10:00]|Server2 |[Total -> 100.0, used -> 35.0, buffer -> 8.0, cached -> 10.0]|
+------------------------------------------+--------+-------------------------------------------------------------+
现在我们定义一些别名和一个简单的select语句:
val total = col("metrics")("Total")
val used = col("metrics")("used")
val buffer = col("metrics")("buffer")
val cached = col("metrics")("cached")
val result = grouped.select($"window", $"Hostname",
(total - ((total - used + buffer + cached) / total) * 100).as("percentage"))
现在我们开始:
+------------------------------------------+--------+----------+
|window |Hostname|percentage|
+------------------------------------------+--------+----------+
|[2019-08-17 10:00:00, 2019-08-17 10:05:00]|Server1 |17.0 |
|[2019-08-17 10:00:00, 2019-08-17 10:05:00]|Server2 |26.0 |
|[2019-08-17 10:05:00, 2019-08-17 10:10:00]|Server1 |17.0 |
|[2019-08-17 10:05:00, 2019-08-17 10:10:00]|Server2 |17.0 |
+------------------------------------------+--------+----------+
当转换为列的值列表未知时,数据透视的成本很高。Spark有一个重载的
pivot
方法,将它们作为参数
def pivot(pivotColumn: String, values: Seq[Any])
如果它们未知,Spark必须从数据集中排序和收集不同的值。否则,逻辑就相当简单,并且描述得很好
该实现添加了一个新的逻辑运算符(o.a.s.sql.catalyst.plans.logical.Pivot)。该逻辑运算符由新的analyzer规则(o.a.s.sql.catalyst.analysis.analyzer.ResolvePivot)转换,该规则当前将其转换为包含大量if语句的聚合,每个pivot值一个表达式
例如,df.groupBy(“A”,“B”).pivot(“C”,Seq(“small”,“large”).sum(“D”)将被转换为df.groupBy(“A”,“B”).agg(expr(“sum”(如果(C='small',D,null)))的等价物,expr(“sum”(如果(C='large',D,null)))。您可以自己做这件事,但它会变得很长,而且可能很快就会出错
如果不旋转,我会这样做:
val in = spark.read.csv("input.csv")
//cast to the unix timestamp
.withColumn("timestamp", unix_timestamp($"time_stamp", "yyyy/MM/dd HH:mm:ss").cast(TimestampType))
.drop($"time_stamp")
现在,我们可以按时间窗口将数据集与主机名分组,并将KPI指标收集到映射中。这是一个很好的描述
val joinMap = udf { values: Seq[Map[String, Double]] => values.flatten.toMap }
val grouped = in.groupBy(window($"timestamp", "5 minutes"), $"Hostname")
.agg(joinMap(collect_list(map($"kpi_subtype", $"value_current".cast(DoubleType)))).as("metrics"))
输出
+------------------------------------------+--------+-------------------------------------------------------------+
|window |Hostname|metrics |
+------------------------------------------+--------+-------------------------------------------------------------+
|[2019-08-17 10:00:00, 2019-08-17 10:05:00]|Server1 |[Total -> 100.0, used -> 35.0, buffer -> 8.0, cached -> 10.0]|
|[2019-08-17 10:00:00, 2019-08-17 10:05:00]|Server2 |[Total -> 100.0, used -> 42.0, buffer -> 7.0, cached -> 9.0] |
|[2019-08-17 10:05:00, 2019-08-17 10:10:00]|Server1 |[Total -> 100.0, used -> 35.0, buffer -> 8.0, cached -> 10.0]|
|[2019-08-17 10:05:00, 2019-08-17 10:10:00]|Server2 |[Total -> 100.0, used -> 35.0, buffer -> 8.0, cached -> 10.0]|
+------------------------------------------+--------+-------------------------------------------------------------+
现在我们定义一些别名和一个简单的select语句:
val total = col("metrics")("Total")
val used = col("metrics")("used")
val buffer = col("metrics")("buffer")
val cached = col("metrics")("cached")
val result = grouped.select($"window", $"Hostname",
(total - ((total - used + buffer + cached) / total) * 100).as("percentage"))
现在我们开始:
+------------------------------------------+--------+----------+
|window |Hostname|percentage|
+------------------------------------------+--------+----------+
|[2019-08-17 10:00:00, 2019-08-17 10:05:00]|Server1 |17.0 |
|[2019-08-17 10:00:00, 2019-08-17 10:05:00]|Server2 |26.0 |
|[2019-08-17 10:05:00, 2019-08-17 10:10:00]|Server1 |17.0 |
|[2019-08-17 10:05:00, 2019-08-17 10:10:00]|Server2 |17.0 |
+------------------------------------------+--------+----------+
第一个是在spark中使用pivot,第二个是使用map 第一种解决方案 第二种解决方案
第一个是在spark中使用pivot,第二个是使用map 第一种解决方案 第二种解决方案
每次服务器1和服务器2都会有多个记录集?是的,每5分钟我们将获得相同的数据集第一组服务器1和服务器2的时间范围是什么?是5分钟吗?它是否会延长到5分钟以上,还是会保持在该时间范围内?每5分钟将有一组相同的服务器。在实际情况下,大约有20000台服务器每次您将有多个服务器1和服务器2的记录集?是的,每5分钟我们将获得相同的数据集第一组服务器1和服务器2的时间范围是什么?是5分钟吗?它是否会延长到5分钟以上,还是会保持在该时间范围内?每5分钟将有一组相同的服务器。在real中,大约有20000台服务器。。。我相信这段代码是用scala编写的。由于我的其余代码在pyspark中,因此需要将其与现有代码集成。所有使用的函数都是Spark函数,python中没有吗?joinMap=udf({values:Seq[Map[String,Double]]=>values.flatte.toMap})。我将其修改为python,但符号“=>”出现sytax错误,请改用
python
UDF语法:。此外,您的类型也不同,这里有一个python示例。谢谢我已经想出了另一个Pypark codeHi。。。我相信这段代码是用scala编写的。由于我的其余代码在pyspark中,因此需要将其与现有代码集成。所有使用的函数都是Spark函数,python中没有吗?joinMap=udf({values:Seq[Map[String,Double]]=>values.flatte.toMap})。我将其修改为python,但符号“=>”出现sytax错误,请改用python
UDF语法:。此外,您的类型也不同,这里有一个python示例。谢谢我已经想出了另一个Pypark codenice。正在寻找在HiveI中执行此操作的方法。我没有使用hive,因此没有意识到这一点。很好。正在寻找在HiveI中执行此操作的方法。我没有使用hive,因此没有意识到这一点。