Разделение списка внутри Pandas DataFrame

У меня есть файл csv, который содержит несколько столбцов. Используя pandas, я прочитал этот файл csv в dataframe и имел индекс datetime и пять или шесть других столбцов.

Одним из столбцов является список временных меток (пример ниже с индексом)

CreateDate TimeStamps 4/1/11 [Timestamp('2012-02-29 00:00:00'), Timestamp('2012-03-31 00:00:00'), Timestamp('2012-04-25 00:00:00'), Timestamp('2012-06-30 00:00:00')] 4/2/11 [Timestamp('2014-01-31 00:00:00')] 6/8/11 [Timestamp('2012-08-31 00:00:00'), Timestamp('2012-09-30 00:00:00'), Timestamp('2012-11-07 00:00:00'), Timestamp('2013-01-10 00:00:00'), Timestamp('2013-07-25 00:00:00')] 

То, что я хотел бы сделать, – это преобразовать столбец timestamp в отдельные строки для каждой отметки времени. Например, для строки 1 она преобразуется в 4 строки, а строка 2 преобразуется в 1 строку. Я понимаю, что мне нужно будет сбросить индекс, чтобы это сделать, и это нормально.

Все, что я пробовал, просто попадает в левое поле (беря значения и создавая список за пределами панд и т. Д.),

Любые предложения оценили.

  • OOP python - удаление экземпляра класса из списка
  • Python: удалить деление после запятой
  • TensorFlow: запуск training_op вечно ведется
  • Python 2.7.5 на Cygwin64: установка запросов не выполняется
  • Указание имен файлов по умолчанию с помощью argparse, но не открытие их на --help?
  • Обнаружение щелчков мыши в окнах с использованием python
  • Сортировка списка кортежей по второму элементу (целочисленное значение)
  • Почему этот оператор if вызывает синтаксическую ошибку
  • 4 Solutions collect form web for “Разделение списка внутри Pandas DataFrame”

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

     In [1]: import pandas as pd In [2]: d = {'date': ['4/1/11', '4/2/11'], 'ts': [[pd.Timestamp('2012-02-29 00:00:00'), pd.Timestamp('2012-03-31 00:00:00'), pd.Timestamp('2012-04-25 00:00:00'), pd.Timestamp('2012-06-30 00:00:00')], [pd.Timestamp('2014-01-31 00:00:00')]]} In [3]: df = pd.DataFrame(d) In [4]: df.head() Out[4]: date ts 0 4/1/11 [2012-02-29 00:00:00, 2012-03-31 00:00:00, 201... 1 4/2/11 [2014-01-31 00:00:00] In [5]: df_new = df.groupby('date').ts.apply(lambda x: pd.DataFrame(x.values[0])).reset_index().drop('level_1', axis = 1) In [6]: df_new.columns = ['date','ts'] In [7]: df_new.head() Out[7]: date ts 0 4/1/11 2012-02-29 1 4/1/11 2012-03-31 2 4/1/11 2012-04-25 3 4/1/11 2012-06-30 4 4/2/11 2014-01-31 

    Поскольку цель состоит в том, чтобы принять значение столбца (в этом случае date) и повторить его для всех значений нескольких строк, которые вы намереваетесь создать из списка, полезно подумать о индексировании pandas.

    Мы хотим, чтобы дата стала единственным индексом для новых строк, поэтому мы используем groupby который ставит нужное значение строки в индекс. Затем внутри этой операции я хочу разделить только этот список на эту дату, и это apply для нас.

    Я передаю apply Series pandas, которая состоит из одного списка, но я могу получить доступ к этому списку через .values[0] который подталкивает единственную строку Series к массиву с одной записью.

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

    Как только это будет возвращено, у меня есть мультииндекс, но я могу заставить это в формате строки, который мы желаем, с помощью reset_index . Затем мы просто удаляем нежелательный индекс.

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

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

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

     df_new = df.groupby('date').ts.apply(lambda x: pd.DataFrame([item for sublist in x.values for item in sublist])) 

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

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

     In [48]: df = pd.DataFrame([[1,2,[1,2,4]],[4,5,[1,3]],],columns=['a','b','TimeStamp']) ...: df Out[48]: ab TimeStamp 0 1 2 [1, 2, 4] 1 4 5 [1, 3] 

    Вы можете преобразовать столбец в список, а затем вернуться к DataFrame чтобы разбить его на столбцы:

     In [53]: TScolumns = pd.DataFrame(df.TimeStamp.tolist(), ) ...: TScolumns Out[53]: 0 1 2 0 1 2 4 1 1 3 NaN 

    И затем соедините его с исходным фреймворком данных

     In [90]: df = df.drop('TimeStamp',axis=1) In [58]: split = pd.concat([df, TScolumns], axis=1) ...: split Out[58]: ab 0 1 2 0 1 2 1 2 4 1 4 5 1 3 NaN 

    Наконец, используйте melt чтобы получить его в нужную вам форму:

     In [89]: pd.melt(split, id_vars=['a', 'b'], value_name='TimeStamp') Out[89]: ab variable TimeStamp 0 1 2 0 1 1 4 5 0 1 2 1 2 1 2 3 4 5 1 3 4 1 2 2 4 5 4 5 2 NaN 

    Вероятно, это не лучший способ с точки зрения производительности, но, тем не менее, вы можете использовать пакет itertools :

     from pandas import DataFrame, Timestamp import itertools d = {'date': ['4/1/11', '4/2/11'], 'ts': [[Timestamp('2012-02-29 00:00:00'), Timestamp('2012-03-31 00:00:00'), Timestamp('2012-04-25 00:00:00'), Timestamp('2012-06-30 00:00:00')], [Timestamp('2014-01-31 00:00:00')]]} df = DataFrame(d) res = df.to_dict() data = [] for x in res['date'].keys(): data.append(itertools.izip_longest([res['date'][x]], res['ts'][x], fillvalue=res['date'][x])) new_data = list(itertools.chain.from_iterable(data)) df2 = DataFrame(new_data, columns=['date', 'timestamp']) print df2 

    Будет печать:

      date timestamp 0 4/1/11 2012-02-29 1 4/1/11 2012-03-31 2 4/1/11 2012-04-25 3 4/1/11 2012-06-30 4 4/2/11 2014-01-31 

    Это не очень pythonic, но он работает (если ваш createDate уникален!)

    Применить будет только возвращать больше строк, чем получается с помощью groupby, поэтому мы будем искусственно использовать группу (т. Е. Группировать по столбцу с уникальными значениями, поэтому каждая группа – одна строка).

     def splitRows(x): # Extract the actual list of time-stamps. theList = x.TimeStamps.iloc[0] # Each row will be a dictionary in this list. listOfNewRows = list() # Iterate over items in list of timestamps, # putting each one in a dictionary to later convert to a row, # then adding the dictionary to a list. for i in theList: newRow = dict() newRow['CreateDate'] = x.CreateDate.iloc[0] newRow['TimeStamps'] = i listOfNewRows.append(newRow) # Now convert these dictionaries into rows in a new dataframe and return it. return pd.DataFrame(listOfNewRows) df.groupby('CreateDate', as_index = False, group_keys = False).apply(splitRows) 

    Последующее наблюдение: если CreateDate НЕ уникален, вы можете просто сбросить индекс до нового столбца и группы.

    Python - лучший язык программирования в мире.