Разделение большого кадра данных Pandas с минимальным объемом памяти

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

Есть ли операция, похожая на pop, но для большого сегмента, которая одновременно удалит часть DataFrame и позволит мне назначить ее новому DataFrame? Что-то вроде этого:

# Assume I have initialized a DataFrame (called "all") which contains my large dataset, # with a boolean column called "test" which indicates whether a record should be used for # testing. print len(all) # 10000000 test = all.pop_large_segment(all[test]) # not a real command, just a place holder print len(all) # 8000000 print len(test) # 2000000 

3 Solutions collect form web for “Разделение большого кадра данных Pandas с минимальным объемом памяти”

Если у вас есть место для добавления еще одного столбца, вы можете добавить его со случайным значением, которое вы могли бы фильтровать для тестирования. Здесь я использовал форму между 0 и 1, но вы могли бы использовать что угодно, если бы хотели другую пропорцию.

 df = pd.DataFrame({'one':[1,2,3,4,5,4,3,2,1], 'two':[6,7,8,9,10,9,8,7,6], 'three':[11,12,13,14,15,14,13,12,11]}) df['split'] = np.random.randint(0, 2, size=len(df)) 

Конечно, это требует, чтобы у вас было место, чтобы добавить совершенно новый столбец, особенно если ваши данные очень длинные, может быть, нет.

Другой вариант будет работать, например, если ваши данные были в формате csv, и вы знали количество строк. Сделайте схожую с randomint с помощью randomint , но передайте этот список в аргумент skiprows для Pandas read_csv() :

 num_rows = 100000 all = range(num_rows) some = np.random.choice(all, replace=False, size=num_rows/2) some.sort() trainer_df = pd.read_csv(path, skiprows=some) rest = [i for i in all if i not in some] rest.sort() df = pd.read_csv(path, skiprows=rest) 

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

Чтобы сделать его еще более дружественным к памяти, вы можете загрузить подмножество тренера, подготовить модель, а затем перезаписать учебный информационный кадр с остальной частью данных, а затем применить модель. Вы будете зависнуть, неся some и rest , но вам никогда не придется загружать обе половинки данных одновременно.

Я бы сделал что-то подобное, как @ jeff-l, т. Е. Сохранил фрейм данных в файле. Когда вы читаете его как csv, используйте ключевое слово chunksize . Следующий сценарий иллюстрирует это:

 import pandas import numpy test = 5 m, n = 2*test, 3 df = pandas.DataFrame( data=numpy.random.random((m, n)) ) df['test'] = [0] * test + [1] * test df.to_csv('tmp.csv', index=False) for chunk in pandas.read_csv('tmp.csv', chunksize=test): print chunk del chunk 

Поскольку другие ответы более сосредоточены на чтении файла, я думаю, вы также можете что-то сделать, если по какой-либо причине ваш DataFrame не читается из файла.

Возможно, вы можете взглянуть на код метода DataFrame.drop и изменить его, чтобы изменить свой DataFrame inplace (который уже существует метод drop ) и вернуть другие возвращаемые файлы:

 class DF(pd.DataFrame): def drop(self, labels, axis=0, level=None, inplace=False, errors='raise'): axis = self._get_axis_number(axis) axis_name = self._get_axis_name(axis) axis, axis_ = self._get_axis(axis), axis if axis.is_unique: if level is not None: if not isinstance(axis, pd.MultiIndex): raise AssertionError('axis must be a MultiIndex') new_axis = axis.drop(labels, level=level, errors=errors) else: new_axis = axis.drop(labels, errors=errors) dropped = self.reindex(**{axis_name: new_axis}) try: dropped.axes[axis_].set_names(axis.names, inplace=True) except AttributeError: pass result = dropped else: labels = com._index_labels_to_array(labels) if level is not None: if not isinstance(axis, MultiIndex): raise AssertionError('axis must be a MultiIndex') indexer = ~axis.get_level_values(level).isin(labels) else: indexer = ~axis.isin(labels) slicer = [slice(None)] * self.ndim slicer[self._get_axis_number(axis_name)] = indexer result = self.ix[tuple(slicer)] if inplace: dropped = self.ix[labels] self._update_inplace(result) return dropped else: return result, self.ix[labels] 

Что будет работать следующим образом:

 df = DF({'one':[1,2,3,4,5,4,3,2,1], 'two':[6,7,8,9,10,9,8,7,6], 'three':[11,12,13,14,15,14,13,12,11]}) dropped = df.drop(range(5), inplace=True) # or : # partA, partB = df.drop(range(5)) 

Этот пример, вероятно, не очень эффективен с точки зрения памяти, но, возможно, вы можете найти что-то лучше, используя какое-то объектно-ориентированное решение, подобное этому.

  • Выберите несколько групп из объекта pandas groupby
  • Объект DataFrame не может быть вызван
  • Pandas читает csv без заголовка (который может быть там)
  • Slice Pandas DataFrame by Row
  • Серия Python Pandas от Datetimes до Seconds Начиная с эпохи
  • Как ускорить поиск кода по кадру данных занимает часы
  • Общая строка данных панд
  • Мне нужно создать объект списка python или любой объект из объекта pandas DataFrame, группирующего фрагменты значений из разных строк
  •  
    Interesting Posts for Van-Lav
    Python - лучший язык программирования в мире.