Декартово произведение двух больших информационных фреймов, сохраняя значения, которые удовлетворяют условию - PullRequest
0 голосов
/ 07 февраля 2019

Так что моя проблема может быть наивной, но я долго искал и все еще не могу найти ответ.У меня есть два больших набора данных:

  1. Один - это файл переписи, содержащий более 700 000 записей.

    Lastname Census     1stname Census     census_year                
    C2last                C2first            1880
    C3last                C3first            1850
    C4last                C4first            1850
    
  2. Другой пример представляет собой регистр актов гражданского состояния, состоящий из 80 000 наблюдений.

    Lastname Reg      1stname reg       birth_year               
    P2Last              P2first         1818
    P3last              P3first         1879
    P4last              P4first         1903
    

Мне нужно выполнить декартово произведение обоих наборов данных, которое, очевидно, представляет собой огромный файл (700 000 x 80 000), где для каждой строки переписи мы должны бытьдобавив 80000 регистров гражданского состояния с дополнительной переменной.

Значения этой дополнительной переменной удовлетворяют условию.Условие состоит в том, что год переписи (переменная переписи) больше, чем переменная 'год рождения' в реестрах актов гражданского состояния (или, другими словами, год переписи моложе, чем число рожденных в реестре).

Как я уже сказал, цель состоит в том, чтобы сделать декартово произведение, но добавив дополнительную переменную (флаг), которая дает «1» при выполнении условия (год переписи> год рождения) или «0», когдане:

LastNCens  1stNCens   cens_year  LastNamReg   1stNamReg       birth      Flag
C2last     C2first         1880      P2Last     P2first        1818         1
                                     P3last     P3first        1879         1
                                     P4last     P4first        1903         0
C3last     C3first         1850      P2Last     P2first        1818         1
                                     P3last     P3first        1879         0
                                     P4last     P4first        1903         0
C4last     C4first         1860      P2Last     P2first        1818         1
                                     P3last     P3first        1879         0
                                     P4last     P4first        1903         0

Все это, учитывая, что продукт слишком велик.

Я пробовал много вещей (сравнивать, различать, пересекать), и я читал и другие вещи.что я не мог применить (df.where, pd.merge), но они не делают то, что мне нужно, и я не могу использовать их здесь.Мой простой подход был бы следующим:

cp <-  merge(census, register,by=NULL);

final.dataframe <- cp [which (cp$census_year > cp$birth_year_hsn ),]

Но R не хватает памяти.

Само собой разумеется, что результирующий фрейм данных (декартово произведение) также будет действительным только с темизаписи, помеченные как '1' (избавление от записей с Flag='0').

Я надеюсь, что это хорошо объяснено и также полезно для других людей ... Большое спасибо за любой совет.Это очень приветствуется.

1 Ответ

0 голосов
/ 28 февраля 2019

Вместе с комментариями к вопросу можно достичь того, что вы ищете, используя пакет data.table.Пакет изменяется по ссылке и, как таковой, может помочь уменьшить объем памяти, используемой для подмножеств, слияний и вычислений.Для получения дополнительной информации о пакете я предлагаю использовать их страницу википедии github , которая содержит краткий шпаргалку для большинства вычислений.

Ниже приведен пример того, как можно выполнить такое слияниечто вы ищете, используя data.table.Это упоминается как non-equi join.Несколько заметок .Похоже, в пакете data.table присутствует ошибка, которая еще не была замечена.by = .EACHI кажется необходимым при выводе обоих соединенных столбцов, чтобы получить исходные значения левой части объединения.Однако это небольшая стоимость.

df1 <- fread("Lastname_Census     firstname_Census     census_year                
              C2last                C2first            1880
              C3last                C3first            1850
              C4last                C4first            1850", key = "census_year")
df2 <- fread("Lastname_Reg      firstname_reg       birth_year               
              P2Last              P2first         1818
              P3last              P3first         1879
              P4last              P4first         1903", key = "birth_year")

cart_join <- 
    df2[df1, #join df1 on df2
      on = .(birth_year >= census_year), #join criteria
      #Force keep all columns to keep (i.var, indicates to keep var from df1)
      j = .(i.Lastname_Census,
            i.firstname_Census, 
            Lastname_Reg, 
            firstname_reg, 
            birth_year, 
            i.census_year, 
            Flag = birth_year >= i.census_year), 
      #Force evaluation on each i. This will keep the correct birth_year (seems to be a bug)
      by = .EACHI,
      #Let the table grow beyond nrow(df1) + nrow(df2) 
      allow.cartesian = TRUE][,-1] #Remove the first column. It is a merge column

Редактировать (несколько возможных ошибок)

Поиграв с объединением, я заметил несколько неровностей и последовал за этим, открыв проблему здесь .Обратите внимание, что вы должны быть осторожны с моим предложенным выше ответом.Кажется, что он работает нормально при возврате значений из обеих таблиц (кроме тех, которые использовались в операторе on), но он не является непроницаемымПожалуйста, обратитесь к моей открытой проблеме для получения дополнительной информации.

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