拆分Pandas DataFrame中的List

Eri*_*own 10 python csv pandas

我有一个包含许多列的csv文件.使用pandas,我将这个csv文件读入一个数据帧,并有一个日期时间索引和五到六个其他列.

其中一列是时间戳列表(下面带索引的示例)

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')]
Run Code Online (Sandbox Code Playgroud)

我想要做的是将时间戳列转换为列出的每个时间戳的单独行.例如,对于第1行,它将转换为4行,第2行将转换为1行.我意识到我需要重置索引才能做到这一点,这很好.

我尝试过的所有东西最终都会进入左侧区域(获取值并在熊猫之外创建一个列表等)

任何建议赞赏.

cwh*_*and 12

如果你想留在纯大熊猫中,你可能会陷入困境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
Run Code Online (Sandbox Code Playgroud)

由于目标是获取列的值(在本例中为date)并对要从列表中创建的多行的所有值重复它,因此考虑pandas索引是有用的.

我们希望日期成为新行的单个索引,因此我们使用groupby它将所需的行值放入索引中.然后在该操作中我想仅拆分这个日期的列表,这将是我们apply将要做的.

我正在传递apply一个Series由单个列表组成的熊猫,但是我可以通过将该列表.values[0]的唯一行推Series送到具有单个条目的数组来访问该列表.

要将列表转换为一组将传递回索引日期的行,我可以将其设置为a DataFrame.这导致了获得额外指数的惩罚,但我们最终放弃了.我们可以将其作为索引本身,但这将排除重复值.

一旦传回这个,我有一个多索引,但我可以将其强制为我们想要的行格式reset_index.然后我们简单地删除不需要的索引.

这听起来很复杂,但实际上我们只是利用pandas函数的自然行为来避免显式迭代或循环.

速度方面,这往往是相当不错的,因为它依赖于apply任何与此同时工作的并行化技巧apply.

(可选)如果您希望它对多个日期都很健壮,每个日期都有一个嵌套列表:

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

在这一点上,一个衬管变得密集,你应该投入一个功能.


ari*_*ari 6

我这样做的方法是将列表拆分成单独的列,然后melt编辑它以将每个时间戳放在一个单独的行中.

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

您可以将列转换为列表,然后返回到a DataFrame以将其拆分为列:

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

然后将其拼接到原始数据帧上

In [90]: df = df.drop('TimeStamp',axis=1)
In [58]: split = pd.concat([df, TScolumns], axis=1)
    ...: split
Out[58]: 
   a  b  0  1   2
0  1  2  1  2   4
1  4  5  1  3 NaN
Run Code Online (Sandbox Code Playgroud)

最后,用melt它将它变成你想要的形状:

In [89]: pd.melt(split, id_vars=['a', 'b'], value_name='TimeStamp')
Out[89]: 
   a  b 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
Run Code Online (Sandbox Code Playgroud)


nic*_*_eu 1

这感觉不太Pythonic,但它有效(前提是你的createDate是唯一的!)

Apply 只会返回比使用 groupby 获得的行数更多的行,因此我们将人为地使用 groupby (即 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)
Run Code Online (Sandbox Code Playgroud)

后续:如果 CreateDate 不唯一,您可以将索引重置为新列并对其进行分组。