如何针对一行使用groupby?
how to use groupby with respect of a row?
我想对一行进行分组:
col1 col2 col3 col4 col5
'A' 'B' 'B' 'A' 'B'
2 4 3 2 1
0 1 2 4 0
1 1 1 1 1
如果第一行中的两列具有相同的值,我想过滤此数据框并输入它们的平均值。
例如,第一列和第四列在第一行中具有相同的值“A”,这些行的平均值为:
first row: (2+2)/2=2
second row: (0+4)/2=2
third row: (1+1)/2=1
对于值为 B
的列也是如此。所以输出是
col1 col2
'A' 'B'
2 7/3
2 3/3
1 3/3
正如我在评论中提到的,将字符串和整数混合在一个列中并不实用。最好将字母行作为列名的一部分,或者将此数据框旋转为将字母行作为列。
我将展示如何将字母行作为列名的一部分并从那里获取平均值。
df = spark.createDataFrame([
['A', 'B', 'B', 'A', 'B'],
['2', '4', '3', '2', '1'],
['0', '1', '2', '4', '0'],
['1', '1', '1', '1', '1']
], ['col1', 'col2', 'col3', 'col4', 'col5'])
letter_row = df.filter(df.col1.rlike('[^\d]')).take(1)[0]
new_cols = [f'{letter_row[x]}_{x}' for x in letter_row.asDict()]
df = df.filter(df.col1.rlike('\d+')).toDF(*new_cols)
# df.show()
# +------+------+------+------+------+
# |A_col1|B_col2|B_col3|A_col4|B_col5|
# +------+------+------+------+------+
# | 2| 4| 3| 2| 1|
# | 0| 1| 2| 4| 0|
# | 1| 1| 1| 1| 1|
# +------+------+------+------+------+
acols = [x for x in df.columns if x.startswith('A_')]
bcols = [x for x in df.columns if x.startswith('B_')]
df = (df.withColumn('A_avg', sum(F.col(x) for x in acols) / len(acols))
.withColumn('B_avg', sum(F.col(x) for x in bcols) / len(bcols)))
结果
+------+------+------+------+------+-----+-----+
|A_col1|B_col2|B_col3|A_col4|B_col5|A_avg|B_avg|
+------+------+------+------+------+-----+-----+
| 2| 4| 3| 2| 1| 2.0| 2.66|
| 0| 1| 2| 4| 0| 2.0| 1.0|
| 1| 1| 1| 1| 1| 1.0| 1.0|
+------+------+------+------+------+-----+-----+
我想对一行进行分组:
col1 col2 col3 col4 col5
'A' 'B' 'B' 'A' 'B'
2 4 3 2 1
0 1 2 4 0
1 1 1 1 1
如果第一行中的两列具有相同的值,我想过滤此数据框并输入它们的平均值。
例如,第一列和第四列在第一行中具有相同的值“A”,这些行的平均值为:
first row: (2+2)/2=2
second row: (0+4)/2=2
third row: (1+1)/2=1
对于值为 B
的列也是如此。所以输出是
col1 col2
'A' 'B'
2 7/3
2 3/3
1 3/3
正如我在评论中提到的,将字符串和整数混合在一个列中并不实用。最好将字母行作为列名的一部分,或者将此数据框旋转为将字母行作为列。
我将展示如何将字母行作为列名的一部分并从那里获取平均值。
df = spark.createDataFrame([
['A', 'B', 'B', 'A', 'B'],
['2', '4', '3', '2', '1'],
['0', '1', '2', '4', '0'],
['1', '1', '1', '1', '1']
], ['col1', 'col2', 'col3', 'col4', 'col5'])
letter_row = df.filter(df.col1.rlike('[^\d]')).take(1)[0]
new_cols = [f'{letter_row[x]}_{x}' for x in letter_row.asDict()]
df = df.filter(df.col1.rlike('\d+')).toDF(*new_cols)
# df.show()
# +------+------+------+------+------+
# |A_col1|B_col2|B_col3|A_col4|B_col5|
# +------+------+------+------+------+
# | 2| 4| 3| 2| 1|
# | 0| 1| 2| 4| 0|
# | 1| 1| 1| 1| 1|
# +------+------+------+------+------+
acols = [x for x in df.columns if x.startswith('A_')]
bcols = [x for x in df.columns if x.startswith('B_')]
df = (df.withColumn('A_avg', sum(F.col(x) for x in acols) / len(acols))
.withColumn('B_avg', sum(F.col(x) for x in bcols) / len(bcols)))
结果
+------+------+------+------+------+-----+-----+
|A_col1|B_col2|B_col3|A_col4|B_col5|A_avg|B_avg|
+------+------+------+------+------+-----+-----+
| 2| 4| 3| 2| 1| 2.0| 2.66|
| 0| 1| 2| 4| 0| 2.0| 1.0|
| 1| 1| 1| 1| 1| 1.0| 1.0|
+------+------+------+------+------+-----+-----+