Проверка на равные значения 2 разных кадров данных строка за строкой - PullRequest
1 голос
/ 22 февраля 2020

У меня есть 2 разных фрейма данных, один имеет 5,5 МБ, а другой - 25 ГБ. Я хочу проверить, имеют ли эти два фрейма данных одинаковое значение в 2 разных столбцах для каждой строки.

Например,

x 0 0 a
x 1 2  b
y 1 2 c
z 3 4  d

и

x 0 0 w
x 1 2  m
y 5 6 p
z 8 9  q

Я хочу проверить, равны ли столбцы 2 ° и 3 ° для каждой строки, если да, я возвращаю Столбцы 4 ° для обоих фреймов данных. Тогда у меня должно быть:

a w
b m
c m

, 2 кадра данных отсортированы по значениям столбцов 2 ° и 3 °. Я пытаюсь в R, но файл 2 ° (25 ГБ) слишком велик. Как я могу получить этот новый файл «быстрее» (даже несколько часов) ???

Ответы [ 2 ]

2 голосов
/ 22 февраля 2020

С GNU awk для массивов массивов:

$ cat tst.awk
NR==FNR { a[$2,$3][$4]; next }
($2,$3) in a {
    for (val in a[$2,$3]) {
        print val, $4
    }
}

$ awk -f tst.awk small_file large_file
a w
b m
c m

и с любым awk (немного менее эффективно):

$ cat tst.awk
NR==FNR { a[$2,$3] = a[$2,$3] FS $4; next }
($2,$3) in a {
    split(a[$2,$3],vals)
    for (i in vals) {
        print vals[i], $4
    }
}

$ awk -f tst.awk small_file large_file
a w
b m
c m

Выше при чтении small_file (NR==FNR верно только для первого чтения файла - ищите эти переменные на справочной странице awk или в google) создает ассоциативный массив a[], который отображает индекс, созданный из конкатенации 2-го и 3-го полей, в список значений 4-е поле для этих 2-х / 3-х комбинаций полей. Затем при чтении large_file он ищет этот массив для текущей комбинации 2-го и 3-го полей и просматривает все значения, сохраненные для этой комбинации в предыдущей фазе, печатая это значение ($ 4 из small_file) плюс текущие $ 4.

Вы сказали, что ваш маленький файл имеет размер 5,5 МБ, а большой - 25 ГБ. Поскольку 1 МБ составляет около 1 047 600 символов (см. https://www.computerhope.com/issues/chspace.htm), а каждая из ваших строк имеет длину около 8 символов, это означает, что ваш маленький файл имеет длину около 130 тысяч строк, а ваш большой - около 134 миллионов строк, поэтому Я ожидаю, что на компьютере со средним питанием запуск вышеупомянутого должен занять не больше минуты или двух, это, конечно, не займет и часа!

0 голосов
/ 23 февраля 2020

Альтернатива решению Эда Мортона, но с идентичной идеей:

$ cat tst.awk
NR==FNR { a[$2,$3] = a[$2,$3] $4 ORS; next }
($2,$3) in a {
    s=a[$2,$3]; gsub(ORS,OFS $4 ORS,s) 
    printf "%s",s;
}

$ awk -f tst.awk small_file large_file
a w
b m
c m
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...