pyspark считает ненулевые значения для пар в двух столбцах внутри группы

#python #group-by #count #pyspark #null

#python #группировка по #количество #pyspark #null

Вопрос:

У меня есть такие данные

 A    B    C
1   Null  3
1   2     4
2   Null  6
2   2    Null
2   1    2
3   Null 4
  

и я хочу сгруппировать по A, а затем вычислить количество строк, которые не содержат нулевого значения. Итак, результат должен быть

 A    count  
1      1
2      1
3      0
  

Я не думаю, что это сработает …, не так ли?

 df.groupby('A').agg(count('B','C'))
  

Ответ №1:

Лично я бы использовал вспомогательный столбец, указывающий, является ли значение B или C нулевым. Отрицательный результат в этом решении и возвращает 1 или 0. И используйте sum для этого столбца.

 from pyspark.sql.functions import sum, when
# ...
df.withColumn("isNotNull", when(df.B.isNull() | df.C.isNull(), 0).otherwise(1))
    .groupBy("A").agg(sum("isNotNull"))
  

ДЕМОНСТРАЦИЯ:

 df.show()
#  --- ---- ----                                                                  
# | _1|  _2|  _3|
#  --- ---- ---- 
# |  1|null|   3|
# |  1|   2|   4|
# |  2|null|   6|
# |  2|   2|null|
# |  2|   1|   2|
# |  3|null|   4|
#  --- ---- ---- 

df.withColumn("isNotNull", when(df._2.isNull() | df._3.isNull(), 0).otherwise(1)).show()
#  --- ---- ---- --------- 
# | _1|  _2|  _3|isNotNull|
#  --- ---- ---- --------- 
# |  1|null|   3|        0|
# |  1|   2|   4|        1|
# |  2|null|   6|        0|
# |  2|   2|null|        0|
# |  2|   1|   2|        1|
# |  3|null|   4|        0|
#  --- ---- ---- --------- 

df.withColumn("isNotNull", when(df._2.isNull() | df._3.isNull(), 0).otherwise(1))
  .groupBy("_1").agg(sum("isNotNull")).show()
#  --- -------------- 
# | _1|sum(isNotNull)|
#  --- -------------- 
# |  1|             1|
# |  3|             0|
# |  2|             1|
#  --- -------------- 
  

Ответ №2:

Вы можете удалить строки, содержащие нулевые значения, а затем groupby count :

 df.select('A').dropDuplicates().join(
    df.dropna(how='any').groupby('A').count(), on=['A'], how='left'
).show()
 --- ----- 
|  A|count|
 --- ----- 
|  1|    1|
|  3| null|
|  2|    1|
 --- ----- 
  

Если вы не хотите выполнять объединение, создайте другой столбец, чтобы указать, есть ли null в столбцах B или C:

 import pyspark.sql.functions as f
df.selectExpr('*', 
    'case when B is not null and C is not null then 1 else 0 end as D'
).groupby('A').agg(f.sum('D').alias('count')).show()
 --- ----- 
|  A|count|
 --- ----- 
|  1|    1|
|  3|    0|
|  2|    1|
 --- ----- 
  

Комментарии:

1. Привет, Psidom, извините, что я забыл обновить свой вопрос. Пожалуйста, взгляните на отредактированный вопрос. Я действительно не хочу использовать соединение, чтобы сохранить все категории в ‘A’, но с помощью этой процедуры мне нужно выполнить левое соединение, я думаю. Спасибо.