繁体   English   中英

堆栈表 by Pyspark SQL

[英]Stack table by Pyspark SQL

我有这张看起来像这样的桌子在此处输入图像描述

我想使用看起来像这样的火花将它们堆叠起来。

+-----------+--------+-----+
|CountryName|variable|value|
+-----------+--------+-----+
|      Aruba|    1960|  NaN|
|      Aruba|    1961|  NaN|
|      Aruba|    1962|  NaN|
|      Aruba|    1963|  NaN|
|      Aruba|    1964|  NaN|
|      Aruba|    1965|  NaN|
|      Aruba|    1966|  NaN|
|      Aruba|    1967|  NaN|
|      Aruba|    1968|  NaN|
|      Aruba|    1969|  NaN|
|      Aruba|    1970|  NaN|
|      Aruba|    1971|  NaN|
|      Aruba|    1972|  NaN|
|      Aruba|    1973|  NaN|
|      Aruba|    1974|  NaN|
|      Aruba|    1975|  NaN|
|      Aruba|    1976|  NaN|
|      Aruba|    1977|  NaN|
|      Aruba|    1978|  NaN|
|      Aruba|    1979|  NaN|
+-----------+--------+-----+

但出于某种原因,我一直在获取此表,其中第 4 列的值与第 3 列的值相同。 我还有其他办法吗?

+-----------+-----------+----+-----------+
|CountryName|CountryCode|Year|CO2Emission|
+-----------+-----------+----+-----------+
|      Aruba|        ABW|1960|       1960|
|      Aruba|        ABW|1961|       1961|
|      Aruba|        ABW|1962|       1962|
|      Aruba|        ABW|1963|       1963|
|      Aruba|        ABW|1964|       1964|
|      Aruba|        ABW|1965|       1965|
|      Aruba|        ABW|1966|       1966|
|      Aruba|        ABW|1967|       1967|
|      Aruba|        ABW|1968|       1968|
|      Aruba|        ABW|1969|       1969|
|      Aruba|        ABW|1970|       1970|
|      Aruba|        ABW|1971|       1971|
|      Aruba|        ABW|1972|       1972|
|      Aruba|        ABW|1973|       1973|
|      Aruba|        ABW|1974|       1974|
|      Aruba|        ABW|1975|       1975|
|      Aruba|        ABW|1976|       1976|
|      Aruba|        ABW|1977|       1977|
|      Aruba|        ABW|1978|       1978|
|      Aruba|        ABW|1979|       1979|
+-----------+-----------+----+-----------+

这是我的代码:

spark.sql("""
  select CountryName, CountryCode, stack(55,'1960',1960,'1961',1961,'1962',1962,'1963',1963,'1964',1964,'1965',1965,'1966',1966,'1967',1967,'1968',1968,'1969',1969,
  '1970',1970,'1971',1971,'1972',1972,'1973',1973,'1974',1974,'1975',1975,'1976',1976,'1977',1977,'1978',1978,'1979',1979,
  '1980',1980,'1981',1981,'1982',1982,'1983',1983,'1984',1984,'1985',1985,'1986',1986,'1987',1987,'1988',1988,'1989',1989,
  '1990',1990,'1991',1991,'1992',1992,'1993',1993,'1994',1994,'1995',1995,'1996',1996,'1997',1997,'1998',1998,'1999',1999,
  '2000',2000,'2001',2001,'2002',2002,'2003',2003,'2004',2004,'2005',2005,'2006',2006,'2007',2007,'2008',2008,'2009',2009,'2010',
  2010,'2011',2011,'2012',2012,'2013',2013,'2014',2014 ) as (Year, CO2Emission)
  from CO2level
""").show()

请帮我。 我对 Spark 非常陌生。 我稍后需要将它与另一张桌子一起加入所以请告诉我!

使用create_mapexplode函数可以轻松完成:

import pyspark.sql.functions as f

df = spark.read.table("CO2level")
df = df.withColumn(
  "other_cols",
  f.create_map(*[col for col in df.columns if col != "CountryName"])
)
df = df.select("CountryName", f.explode("other_cols").alias("variable","value"))

df.show(truncate=False)

CO2Emission的值与Year完全相同的原因是因为您的列名称数字(例如 1960、1961 等),因此在堆叠'1960',1960时,您将字符串'1960'堆叠在integer 1960之上。 修复它的最简单方法是将 integer 列名包装在一对反引号``中,例如“'1960','1960'”。

这是我的示例数据集
df = spark.createDataFrame([
    ('C1', 'c1', 1, 2, 3),
    ('C2', 'c2', 4, 5, 6),
    ('C3', 'c3', 7, 8, 9),
], ['name', 'code', '1960', '1961', '1962'])

+----+----+----+----+----+
|name|code|1960|1961|1962|
+----+----+----+----+----+
|  C1|  c1|   1|   2|   3|
|  C2|  c2|   4|   5|   6|
|  C3|  c3|   7|   8|   9|
+----+----+----+----+----+
Select 使用反引号
(df
    .select('name', 'code', F.expr('stack(3, "1960", `1960`, "1961", `1961`, "1962", `1962`)'))
    .show()
)

+----+----+----+----+
|name|code|col0|col1|
+----+----+----+----+
|  C1|  c1|1960|   1|
|  C1|  c1|1961|   2|
|  C1|  c1|1962|   3|
|  C2|  c2|1960|   4|
|  C2|  c2|1961|   5|
|  C2|  c2|1962|   6|
|  C3|  c3|1960|   7|
|  C3|  c3|1961|   8|
|  C3|  c3|1962|   9|
+----+----+----+----+
缩短代码

您可能已经意识到带有所有硬编码列的长select没有任何好处,更不用说模式可能会更改并且可能会发生错误。 您可以使用 for 循环来获取列名并构建一个字符串,而不是将它们写下来。

cols = [f'"{c}", `{c}`' for c in df.columns if c not in ['name', 'code']]
# ['"1960", `1960`', '"1961", `1961`', '"1962", `1962`']

(df
    .select('name', 'code', F.expr(f'stack({len(cols)}, {",".join(cols)})'))
    .show()
)

+----+----+----+----+
|name|code|col0|col1|
+----+----+----+----+
|  C1|  c1|1960|   1|
|  C1|  c1|1961|   2|
|  C1|  c1|1962|   3|
|  C2|  c2|1960|   4|
|  C2|  c2|1961|   5|
|  C2|  c2|1962|   6|
|  C3|  c3|1960|   7|
|  C3|  c3|1961|   8|
|  C3|  c3|1962|   9|
+----+----+----+----+

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM