У меня есть, pandas dataframe
в котором один столбец текстовых строк содержит значения, разделенные запятыми. Я хочу разделить каждое поле CSV и создать новую строку для каждой записи (предположим, что CSV чисты и должны быть разделены только на ','). Например, a
должно стать b
:
In [7]: a
Out[7]:
var1 var2
0 a,b,c 1
1 d,e,f 2
In [8]: b
Out[8]:
var1 var2
0 a 1
1 b 1
2 c 1
3 d 2
4 e 2
5 f 2
До сих пор я пробовал различные простые функции, но .apply
метод, кажется, принимает только одну строку в качестве возвращаемого значения, когда она используется на оси, и я не могу приступить .transform
к работе. Любые предложения будут высоко ценится!
Пример данных:
from pandas import DataFrame
import numpy as np
a = DataFrame([{'var1': 'a,b,c', 'var2': 1},
{'var1': 'd,e,f', 'var2': 2}])
b = DataFrame([{'var1': 'a', 'var2': 1},
{'var1': 'b', 'var2': 1},
{'var1': 'c', 'var2': 1},
{'var1': 'd', 'var2': 2},
{'var1': 'e', 'var2': 2},
{'var1': 'f', 'var2': 2}])
Я знаю, что это не сработает, потому что мы теряем метаданные DataFrame при прохождении через numpy, но это должно дать вам представление о том, что я пытался сделать:
def fun(row):
letters = row['var1']
letters = letters.split(',')
out = np.array([row] * len(letters))
out['var1'] = letters
a['idx'] = range(a.shape[0])
z = a.groupby('idx')
z.transform(fun)
Ответы:
Как насчет чего-то вроде этого:
Тогда вам просто нужно переименовать столбцы
источник
UPDATE2: более общая векторизованная функция, которая будет работать для нескольких
normal
и несколькихlist
столбцовДемо-версия:
Несколько
list
столбцов - всеlist
столбцы должны иметь одинаковое количество элементов в каждой строке:сохранение исходных значений индекса:
Настроить:
Столбец CSV:
используя этот маленький трюк, мы можем преобразовать CSV-подобный столбец в
list
столбец:ОБНОВЛЕНИЕ: универсальный векторизованный подход (будет работать также для нескольких столбцов):
Оригинальный DF:
Решение:
Сначала давайте конвертируем строки CSV в списки:
Теперь мы можем сделать это:
СТАРЫЙ ответ:
Вдохновленный решением @AFinkelstein , я хотел сделать его немного более обобщенным, который можно было бы применить к DF с более чем двумя столбцами и так же быстро, а почти так же быстро, как решение AFinkelstein):
источник
.explode()
метод в API (см. Также этот ответ ).После мучительных экспериментов, чтобы найти что-то быстрее, чем принятый ответ, я заставил это работать. Он работал примерно в 100 раз быстрее на наборе данных, на котором я его пробовал.
Если кто-то знает способ сделать это более элегантным, непременно измените мой код. Я не мог найти способ, который бы работал, не устанавливая другие столбцы, которые вы хотите сохранить в качестве индекса, а затем сбрасывая индекс и переименовывая столбцы, но я думаю, что есть еще кое-что, что работает.
источник
TypeError: object of type 'float' has no len()
DataFrame(df.var1.str.split(',').tolist())
NaN
в этом столбце, поэтому заменаb = DataFrame(a.var1.str.split(',').values.tolist(), index=a.var2).stack()
Вот функция, которую я написал для этой общей задачи. Это более эффективно, чем
Series
/stack
методы. Порядок и названия столбцов сохраняются.С помощью этой функции исходный вопрос так же прост:
источник
Панды> = 0,25
Методы Series и DataFrame определяют
.explode()
метод, который разбивает списки на отдельные строки. См. Раздел «Документы» в разделе « Взрыв столбца в виде списка» .Поскольку у вас есть список строк, разделенных запятыми, разбейте строку на запятую, чтобы получить список элементов, а затем вызовите
explode
этот столбец.Обратите внимание, что
explode
работает только на одном столбце (пока).NaNs и пустые списки получают лечение, которого они заслуживают, без необходимости прыгать через обручи, чтобы сделать это правильно.
Это серьезное преимущество по сравнению с решениями на основе
ravel
+repeat
(которые полностью игнорируют пустые списки и подавляют NaN).источник
Подобный вопрос как: pandas: Как разделить текст в столбце на несколько строк?
Вы могли бы сделать:
источник
s.name = 'var1'
TL; DR
демонстрация
Давайте создадим новый фрейм данных,
d
который имеет спискиОбщие комментарии
Я буду использовать
np.arange
с,repeat
чтобы создать позиции индекса данных, которые я могу использоватьiloc
.Вопросы-Ответы
Почему я не использую
loc
?Поскольку индекс может быть не уникальным, и при использовании
loc
будет возвращаться каждая строка, соответствующая запрашиваемому индексу.Почему бы вам не использовать
values
атрибут и нарезать его?При вызове
values
, если полнота в dataframe в одну сплоченных «блоке», панды возвращают вид массива , который является «блоком». В противном случае Пандам придется собирать новый массив. При слипании этот массив должен иметь одинаковый тип d. Часто это означает возвращение массива с типом dtypeobject
. Используяiloc
вместо разрезанияvalues
атрибута, я избавляю себя от необходимости иметь дело с этим.Почему вы используете
assign
?Когда я использую
assign
использую то же имя столбца, которое я раскрываю, я перезаписываю существующий столбец и сохраняю его положение в кадре данных.Почему значения индекса повторяются?
Благодаря использованию
iloc
на повторяющихся позициях, результирующий индекс показывает тот же повторяющийся паттерн. Один повтор для каждого элемента списка или строки.Это можно сбросить с помощью
reset_index(drop=True)
Для строк
Я не хочу преждевременно раскалывать струны. Поэтому вместо этого я считаю количество
sep
аргументов, предполагая, что если бы я разделил, длина результирующего списка была бы на один больше, чем число разделителей.Я тогда использую это
sep
кjoin
строкам тогдаsplit
.Для списков
Аналогично для строк, за исключением того, что мне не нужно считать
sep
потому что он уже разделен.Я использую Numpy
concatenate
для склеивания списков.источник
Существует возможность разбивать и разбивать фрейм данных без изменения структуры фрейма данных.
Входные данные:
Вне:
Edit-1
Повторное индексирование на основе ссылочного столбца и выравнивание информации о значении столбца со стеком
Вне:
источник
Я придумал решение для фреймов данных с произвольным числом столбцов (при этом одновременно разделяя только записи одного столбца).
источник
Вот довольно простое сообщение, в котором используется
split
методstr
доступа от pandas, а затем используется NumPy для сглаживания каждой строки в одном массиве.Соответствующие значения извлекаются повторением столбца без разделения правильное число раз с
np.repeat
.источник
Я боролся с нехваткой памяти, используя различные способы взорвать мои списки, поэтому я подготовил несколько тестов, чтобы помочь мне решить, какие ответы на upvote. Я протестировал пять сценариев с различными пропорциями длины списка к количеству списков. Поделиться результатами ниже:
Время: (чем меньше, тем лучше, нажмите, чтобы посмотреть большую версию)
Пиковое использование памяти: (чем меньше, тем лучше)
Выводы :
Полная информация (функции и код бенчмаркинга) находится в этой сути GitHub . Обратите внимание, что проблема с эталонным тестом была упрощена и не включала разбиение строк в списке - что большинство решений выполнялось аналогичным образом.
источник
Основываясь на отлично @ DMulligan в растворе , здесь векторизация функция общая (без петель) , который разбивает столбец dataframe на несколько строк и помещает ее обратно к первоначальному dataframe. Он также использует отличную обобщенную
change_column_order
функцию из этого ответа .Пример:
Обратите внимание, что он сохраняет исходный индекс и порядок столбцов. Он также работает с кадрами данных, которые имеют непоследовательный индекс.
источник
Строковая функция split может принимать опциональный логический аргумент 'expand'.
Вот решение, использующее этот аргумент:
источник
Просто использовал превосходный ответ Джилна сверху, но его нужно было расширить, чтобы разделить несколько столбцов. Мысль я бы поделился.
источник
улучшен ответ MaxU с поддержкой MultiIndex
источник
Однострочное использование аргументов
split(___, expand=True)
иlevel
иname
дляreset_index()
:Если вам нужно
b
выглядеть так же, как в вопросе, вы можете сделать следующее:источник
Я придумал следующее решение этой проблемы:
источник
Другое решение, которое использует пакет копирования Python
источник
Здесь есть много ответов, но я удивлен, что никто не упомянул встроенную функцию разнесения панд. Проверьте ссылку ниже: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.explode.html#pandas.DataFrame.explode
По какой-то причине я не смог получить доступ к этой функции, поэтому я использовал следующий код:
Выше приведен образец моих данных. Как вы можете видеть людей колонке было несколько человек, и я пытался взорвать ее. Код, который я дал, работает для данных типа списка. Поэтому постарайтесь получить текстовые данные через запятую в виде списка. Кроме того, так как мой код использует встроенные функции, он намного быстрее, чем пользовательские функции.
Примечание: вам может понадобиться установить pandas_explode с pip.
источник
У меня была похожая проблема, моим решением было сначала преобразовать фрейм данных в список словарей, а затем выполнить переход. Вот функция:
Пример:
Вы также можете немного изменить функцию для поддержки разделения строк типа списка.
источник