Я пытаюсь выполнить тест хи-квадрат в Spark, и я никуда не доберусь.У меня довольно большой набор данных (~ 5 ТБ), поэтому мне действительно нужно использовать Spark для этого - в противном случае я бы использовал Pandas или написал его вручную.Кроме того, число различных значений в столбце может составлять до 10 ^ 5, поэтому я не могу использовать удобный метод кросс-таблицы для вычисления матрицы непредвиденных расходов.
Данные хранятся в DataFrame.Есть около 20 столбцов, но очевидно, что критерий хи-квадрат занимает только два столбца за раз.Мы назовем их столбцами A и B. Я попытался использовать метод кросс-таблицы для построения матрицы непредвиденных обстоятельств.Это прекрасно работает, если количество различных значений в каждом столбце меньше 10 ^ 4, но некоторые из моих столбцов имеют более 10 ^ 5 различных значений.
Я также пытался увеличить ограничение числаразличных ценностей.Несколько связанных вопросов ссылались на spark.sql.pivotmaxvalues, для которого по умолчанию установлено значение 10 ^ 4.Я попробовал spark.conf.set ('spark.sql.pivotmaxvalues', 100000), но это не помогло.
До сих пор мой лучший подход состоял в том, чтобы получить значения A, числа B,подсчет (A, B) и собрать результаты оттуда.Это работает довольно хорошо, потому что число различных пар (A, B) достаточно податливое (что означает, что матрица непредвиденных обстоятельств невелика).Я также должен вернуться и вычислить ожидаемое значение для всех пар (A, B), которые не отображаются в наборе данных.Эта вторая часть занимает гораздо больше времени.
Это лучшее из того, что у меня есть.Предположим, что данные находятся в DataFrame df со строками nRows, а столбцы для тестирования - это A и B.
countA = df.groupBy('A').count()
countA = countA.withColumnRenamed('count', 'NA')
countB = df.groupBy('B').count()
countB = countB.withColumnRenamed('count', 'NB')
countAB = df.groupBy('A', 'B').count()
countAB = countAB.withColumnRenamed('count', 'NAB')
countAB = countAB.join(countA, 'A').join(countB, 'B')
countAB = countAB.withColumn('Expected', countAB['NA'] * countAB['NB'] / nRows)
countAB = countAB.withColumn('Chi2', (countAB['Expected'] - countAB['NAB'])**2 / countAB['Expected'])
missing = countA.crossJoin(countB).join(countAB, ['A', 'B'], 'left_anti')
missing = missing.withColumn('Chi2', missing['NA'] * missing['NB'] / nRows)
total1 = countAB.groupBy().sum('Chi2')
total2 = missing.groupBy().sum('Chi2')
Если я пытаюсь использовать метод кросс-таблицы, я получаю следующую ошибку:
IllegalArgumentException: "требование не выполнено: число различных значений для A не может превышать 1e4. В настоящее время 15387"