Замените NA соответствующими столбцами из очень большого текстового файла. - PullRequest
0 голосов
/ 18 января 2019

У меня большой текстовый файл: 400 тыс. Строк и 10 тыс. Столбцов, все числовые значения данных равны 0,1,2. Размер файла в диапазоне 5-10 ГБ. У меня есть несколько пропущенных значений: NA в файле. Я хочу заменить значения NA значениями столбца, то есть значение NA в столбце «x» должно быть заменено средним значением столбца «x». Вот шаги, которые я хочу сделать:

  1. Вычислить средние значения для каждого столбца моего текстового файла (исключая заголовок и начиная с 7-го столбца)
  2. Заменить NA в каждом столбце на соответствующее значение в столбце
  3. Записать измененный файл обратно как текстовый файл

Подмножество данных :

IID  FID  PAT MAT SEX PHENOTYPE X1 X2 X3 X4......
1234 1234  0  0    1   -9       0  NA  0  1 
2346 2346  0  0    2   -9       1  2  NA  1
1334 1334  0  0    2   -9       2  NA  0  2
4566 4566  0  0    2   -9       2  2  NA  0
4567 4567  0  0    1   -9       NA NA  1  1

# total 400k rows and 10k columns

Желаемый выход :

# Assuming only 5 rows as given in the above example.
# Mean of column X1 = (0 + 1+ 2+ 2)/4 = 1.25
# Mean of column X2 =  (2 + 2)/2 = 2
# Mean of column X3 = (0 + 0 + 1)/3 = 0.33
# Mean of column X4 = No NAs, so no replacements

# Replacing NAs with respective means:

IID  FID  PAT MAT SEX PHENOTYPE X1   X2  X3   X4......
1234 1234  0  0    1   -9       0    2   0     1 
2346 2346  0  0    2   -9       1    2   0.33  1
1334 1334  0  0    2   -9       2    2   0     2
4566 4566  0  0    2   -9       2    2   0.33  0
4567 4567  0  0    1   -9       1.25 2   1     1

Я пробовал это:

file="path/to/data.txt"

#get total number of columns
number_cols=$(awk -F' ' '{print NF; exit}' $file)

for ((i=7; i<=$number_cols; i=i+1))
do 
    echo $i
    # getting the mean of each column
    mean+=$(awk '{ total += $i } END { print total/NR }' $file)
done

# array of column means
echo ${mean[@]}

# find and replace (newstr must be replaced by respective column means)
find $file -type f -exec sed -i 's/NA/newstr/g' {} \;

Однако этот код неполон. Цикл for очень медленный, так как мои данные огромны. Есть ли другой способ сделать это быстрее? Я сделал это в Python и R, но это слишком медленно. Я открыт, чтобы сделать это на любом языке программирования, если это быстро. Может кто-нибудь, пожалуйста, помогите мне написать сценарий?

Спасибо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...