внутреннее объединение с огромными фреймами данных (~ 2 миллиона столбцов) - PullRequest
0 голосов
/ 09 октября 2018

Я пытаюсь объединить два фрейма данных (df1 и df2) на основе сопоставления значений из одного столбца (называемого «Имена»), который находится в каждом фрейме данных.Я попробовал это с помощью функции R inner_join, а также функции Python merge в Python, и смог успешно работать с обоими на меньших подмножествах моих данных.Я думаю, что моя проблема с размером моих фреймов данных.

Мои фреймы данных выглядят следующим образом:

  • df1 имеет столбец «Имена» с 5 дополнительными столбцами и ~ 900 строк.
  • df2 содержит столбец «Имена» с ~ 2 миллионами дополнительных столбцов и ~ 900 строк.

Я пытался (в R):

df3 <- inner_join(x = df1, y = df2, by = 'Name') 

Я также пытался (в Python, где df1 и df2 - фреймы данных Pandas):

df3 = df1.merge(right = df2, how = 'inner', left_on = 1, right_on = 0)   

(где столбец «Имя» имеет индекс 1 для df1 и индекс 0 для df2)

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

Буду признателен за любые предложения, которые кто-нибудь сможет дать.

Ответы [ 2 ]

0 голосов
/ 10 октября 2018

Спасибо всем за помощь!Использование data.table, как предложил @shadowtalker, значительно ускорило процесс.Просто для справки, если кто-то пытается сделать что-то подобное, df1 был примерно 400 МБ, а мой файл df2 был примерно 3 ГБ.

Мне удалось выполнить задачу следующим образом:

library(data.table)
df1 <- setDT(df1)
df2 <- setDT(df2)
setkey(df1, Name)
setkey(df2, Name)
df3 <- df1[df2, nomatch = 0]
0 голосов
/ 10 октября 2018

Это действительно уродливый обходной путь, когда я разбиваю столбцы df2 и добавляю их по частям.Не уверен, что это сработает, но стоит попробовать:

# First, I only grab the "Name" column from df2
df3 = df1.merge(right=df2[["Name"]], how="inner", on="Name")  

# Then I save all the column headers (excluding 
# the "Name" column) in a separate list
df2_columns = df2.columns[np.logical_not(df2.columns.isin(["Name"]))]

# This determines how many columns are going to get added each time.
num_cols_per_loop = 1000

# And this just calculates how many times you'll need to go through the loop
# given the number of columns you set to get added each loop
num_loops = int(len(df2_columns)/num_cols_per_loop) + 1

for i in range(num_loops):
    # For each run of the loop, we determine which rows will get added
    this_column_sublist = df2_columns[i*num_cols_per_loop : (i+1)*num_cols_per_loop]

    # You also need to add the "Name" column to make sure 
    # you get the observations in the right order
    this_column_sublist = np.append("Name",this_column_sublist)

    # Finally, merge with just the subset of df2
    df3 = df3.merge(right=df2[this_column_sublist], how="inner", on="Name")

Как я уже сказал, это уродливый обходной путь, но он может сработать.

...