Серьезно, не нужно идти по динамическому маршруту; используйте
var deser = new JavaScriptSerializer()
.Deserialize<Dictionary<string, Dictionary<string, int>>>(val);
var justDaily = deser["daily"];
, чтобы получить словарь, а затем вы можете, например,
foreach (string key in justDaily.Keys)
Console.WriteLine(key + ": " + justDaily[key]);
, чтобы получить присутствующие клавиши и соответствующие значения.
Вы можете взглянуть на posexplode
. Я использовал ваш небольшой пример и преобразовал фрейм данных в другой фрейм с 5 столбцами и соответствующими значениями из массива в каждой строке.
from pyspark.sql.functions import *
df1 = spark.createDataFrame([([23,4,77,890,455],10),([11,2,50,1,11],20),\
([10,5,1,22,04],30)], ["list1","A"])
df1.select(posexplode("list1"),"list1","A")\ #explodes the array and creates multiple rows for each element with the position in the columns "col" and "pos"
.groupBy("list1","A").pivot("pos")\ #group by your initial values and take the "pos" column as pivot to create 1 new column per element here
.agg(max("col")).show(truncate=False) #collect the values
Вывод:
+---------------------+---+---+---+---+---+---+
|list1 |A |0 |1 |2 |3 |4 |
+---------------------+---+---+---+---+---+---+
|[10, 5, 1, 22, 4] |30 |10 |5 |1 |22 |4 |
|[11, 2, 50, 1, 11] |20 |11 |2 |50 |1 |11 |
|[23, 4, 77, 890, 455]|10 |23 |4 |77 |890|455|
+---------------------+---+---+---+---+---+---+
Конечно, после этого вы можете продолжать вычислять среднее или любое другое значение для отдельных значений массива.
В случае, если ваш столбец list1 содержит строки, а не прямой массив, вам нужно сначала извлечь массив. Вы можете сделать это с помощью regexp_extract
и split
. Это также работает для значений с плавающей запятой в строке.
df1 = spark.createDataFrame([(u'[23.1,4,77,890,455]',10),(u'[11,2,50,1.1,11]',20),(u'[10,5,1,22,04.1]',30)], ["list1","A"])
df1 = df1.withColumn("list2",split(regexp_extract("list1","(([\d\.]+,)+[\d\.]+)",1),","))
df1.select(posexplode("list2"),"list1","A").groupBy("list1","A").pivot("pos").agg(max("col")).show(truncate=False)