如何从dataframe pandas列出列表?

时间:2017-09-30 04:30:27

标签: python list pandas dataframe tuples

我有一个带有单词和标签的Pandas数据框

  words   tags
0 I       WW
1 am      XX
2 newbie  YY
3 .       ZZ
4 You     WW
5 are     XX
6 cool    YY
7 .       ZZ

是否有任何方法可以从数据框中创建列表列表,如下所示:

[[('I', 'WW'), ('am', 'XX'), ('newbie', 'YY'), ('.','ZZ')], 
 [('You', 'WW'), ('are', 'XX'), ('cool', 'YY'), ('.','ZZ')]]

这是元组列表的列表。对于列表中的每个列表,由('.','ZZ')分隔。意思是它是一个句子。

我可以迭代数据帧的每一行并创建列表,如果条件为真,则附加它,但是有没有“熊猫”和#39;解决它的方法?

5 个答案:

答案 0 :(得分:5)

您可以先从所有值创建元组,然后在性能很重要时将它们分隔为子列表:

from  itertools import groupby

L = list(zip(df['words'], df['tags']))
print (L)
[('I', 'WW'), ('am', 'XX'), ('newbie', 'YY'), 
 ('.', 'ZZ'), ('You', 'WW'), ('are', 'XX'), 
 ('cool', 'YY'), ('.', 'ZZ')]

sep = ('.','ZZ')
new_L = [list(g) + [sep] for k, g in groupby(L, lambda x: x==sep) if not k] 
print (new_L)

[[('I', 'WW'), ('am', 'XX'), ('newbie', 'YY'), ('.', 'ZZ')], 
 [('You', 'WW'), ('are', 'XX'), ('cool', 'YY'), ('.', 'ZZ')]]

<强>计时

df = pd.concat([df]*1000).reset_index(drop=True)

def zero(df):
    dft = df.apply(tuple, 1)
    return ([x.values.tolist() for _, x in dft.groupby((dft == ('.', 'ZZ')).shift().cumsum().bfill())])

In [55]: %timeit ([list(g) + [('.','ZZ')] for k, g in groupby(list(zip(df['words'], df['tags'])), lambda x: x==('.','ZZ')) if not k] )
100 loops, best of 3: 4.14 ms per loop

def pir(df):
    v = df.values
    return ([list(map(tuple, x)) for x in np.split(v, np.where((v == ['.', 'ZZ']).all(1)[:-1])[0] + 1)])

In [68]: %timeit (pir(df))
10 loops, best of 3: 21.9 ms per loop


In [56]: %timeit (zero(df))
1 loop, best of 3: 328 ms per loop

In [57]: %timeit (df.groupby((df.shift().values == ['.', 'ZZ']).all(axis=1).cumsum()).apply(lambda group: list(zip(group['words'], group['tags']))).values.tolist())
1 loop, best of 3: 286 ms per loop

In [58]: %timeit (list(filter(None,[i.apply(tuple,1).values.tolist() for i in np.array_split(df,df[(df['words'] == '.') & (df['tags'] == 'ZZ')].index+1)])))
1 loop, best of 3: 1.31 s per loop

对于单独的子列表,我创建了问题,您可以查看解决方案here

def jez_coldspeed(df):
    L = list(zip(df['words'], df['tags']))
    L2 = []
    for i in L[::-1]:
        if i == ('.','ZZ'):
            L2.append([])

        L2[-1].append(i)

    return [x[::-1] for x in L2[::-1]]

def jez_coldspeed1(df):
    L = list(zip(df['words'], df['tags']))
    L2 = []
    sep = ('.','ZZ')
    for i in reversed(L):
         if i == sep:
             L2.append([])

         L2[-1].append(i)

    return [x[::-1] for x in reversed(L2)]


In [74]: %timeit (jez_coldspeed(df))
100 loops, best of 3: 2.96 ms per loop

In [75]: %timeit (jez_coldspeed1(df))
100 loops, best of 3: 2.95 ms per loop
def jez_theBuzzyCoder(df):
    L = list(zip(df['words'], df['tags']))
    a = list()
    start = 0
    sep = ('.', 'ZZ')

    while start < len(L) and (L.index(sep, start) != -1):
        end = L.index(sep, start) + 1
        a.append(L[start:end])
        start = end
    return a


print (jez_theBuzzyCoder(df))

In [81]: %timeit (jez_theBuzzyCoder(df))
100 loops, best of 3: 3.16 ms per loop

答案 1 :(得分:3)

这是单程

In [5149]: dft = df.apply(tuple, 1)

In [5150]: parts = (dft == ('.', 'ZZ')).shift().cumsum().bfill()
           # parts = (dft.shift() == ('.', 'ZZ')).cumsum()       from Alexander's

In [5151]: [x.values.tolist() for _, x in dft.groupby(parts)]
Out[5151]:
[[('I', 'WW'), ('am', 'XX'), ('newbie', 'YY'), ('.', 'ZZ')],
 [('You', 'WW'), ('are', 'XX'), ('cool', 'YY'), ('.', 'ZZ')]]

或者,

In [5152]: dft.groupby(parts).apply(list).tolist()
Out[5152]:
[[('I', 'WW'), ('am', 'XX'), ('newbie', 'YY'), ('.', 'ZZ')],
 [('You', 'WW'), ('are', 'XX'), ('cool', 'YY'), ('.', 'ZZ')]]

或者,

In [5165]: list(dft.groupby(parts).apply(list))
Out[5165]:
[[('I', 'WW'), ('am', 'XX'), ('newbie', 'YY'), ('.', 'ZZ')],
 [('You', 'WW'), ('are', 'XX'), ('cool', 'YY'), ('.', 'ZZ')]]

详细

In [5153]: parts
Out[5153]:
0    0.0
1    0.0
2    0.0
3    0.0
4    1.0
5    1.0
6    1.0
7    1.0
dtype: float64

答案 2 :(得分:3)

你也可以做np.array_split即

li = list(filter(None,[i.apply(tuple,1).values.tolist() \
     for i in np.array_split(df,df[(df['words'] == '.') & (df['tags'] == 'ZZ')].index+1)]))

x = df.apply(tuple,1)
li = [ i.tolist() for i in np.array_split(x,x[x==('.','ZZ')].index+1) if len(i.tolist())>1]

输出:

[[('I', 'WW'), ('am', 'XX'), ('newbie', 'YY'), ('.', 'ZZ')],
 [('You', 'WW'), ('are', 'XX'), ('cool', 'YY'), ('.', 'ZZ')]]

答案 3 :(得分:3)

v = df.values

[
    list(map(tuple, x))
    for x in np.split(v, np.where((v == ['.', 'ZZ']).all(1)[:-1])[0] + 1)
]

[[('I', 'WW'), ('am', 'XX'), ('newbie', 'YY'), ('.', 'ZZ')],
 [('You', 'WW'), ('are', 'XX'), ('cool', 'YY'), ('.', 'ZZ')]]

答案 4 :(得分:1)

第一部分(df.groupby((df.shift().values == ['.', 'ZZ']).all(axis=1).cumsum()))会将数据框分组为“&#39;字”中的连续值。数据帧的列,包括第二列也等于Z的句点。这是shift-cumsum模式的变体(在SO上搜索pandas shift cumsum,您应该找到很多变体)。

第二部分(.apply(lambda group: zip(group['words'], group['tags'])))为每一行创建元组对,例如

0     [(I, WW), (am, XX), (newbie, YY), (., ZZ)]
1    [(You, WW), (are, XX), (cool, YY), (., ZZ)]
dtype: object

最后一部分(.values.tolist())将数据框转换为您想要的格式列表。

>>> df.groupby((df.shift().values == ['.', 'ZZ']).all(axis=1).cumsum()).apply(
        lambda group: zip(group['words'], group['tags'])).values.tolist()
[[('I', 'WW'), ('am', 'XX'), ('newbie', 'YY'), ('.', 'ZZ')],
 [('You', 'WW'), ('are', 'XX'), ('cool', 'YY'), ('.', 'ZZ')]]