将元组列表的列从“应用到新列”中分离出来

时间:2018-07-04 08:39:05

标签: python list pandas dataframe tuples

我有一个看起来像这样的数据框:

df = pd.DataFrame(
    {'tod':    [[('a',10),('b',6),('h',3),('p',2)], 
                [('x',11),('e',2),('l',2)], 
                [('r',5),('l',5)], 
                [('n',15)]]})

                                 tod
0  [(a, 10), (b, 6), (h, 3), (p, 2)]
1          [(x, 11), (e, 2), (l, 2)]
2                   [(r, 5), (l, 5)]
3                          [(n, 15)]

我想将元组列表扩展到新列以获得:

                                 tod l1   n1  l2    n2 l3    n3  l4    n4
0  [(a, 10), (b, 6), (h, 3), (p, 2)]  a   10   b     6  h     3   p     2
1          [(x, 11), (e, 2), (l, 2)]  x   11   e     2  l     2   -   nan
2                   [(r, 5), (l, 5)]  r    5   l     5  -   nan   -   nan
3                          [(n, 15)]  n   15   -   nan  -   nan   -   nan

如果元组不存在,我希望在相应的列中缺少值。

我遇到了麻烦,因为每个单元格中每个行的每个列表的长度(元组数)对于每一行都是不同的,所以我想在出现时动态分配新的列值。另外,每个单元格都包含一个元组对列表,而不是一个元组。

我尝试了类似this问题的方法,但这仅允许将一个元组扩展为多个列(当您事先知道这些列时)。

然后我查看了thisthis,但同样,列数是未知的,所以我得出以下结论:

pd.DataFrame.from_records([{k: v for v, k in row} for row in df.tod])
Out[171]: 
    2    3    5    6    10   11   15
0    p    h  NaN    b    a  NaN  NaN
1    l  NaN  NaN  NaN  NaN    x  NaN
2  NaN  NaN    l  NaN  NaN  NaN  NaN
3  NaN  NaN  NaN  NaN  NaN  NaN    n

然后,我查看了包含元组herehere的拆分单元格,该单元格查看了将元组转换为序列的方法,但是再一次,这没有用,因为这些示例仅处理的单个元组。已知长度,而不是元组列表

我该如何解决这个问题?

注意:我意识到我没有为“您尝试了什么”编写了很多代码-我的控制台是一堆垃圾,产生了连续的错误。为了保持这种清洁,我将其省略。

2 个答案:

答案 0 :(得分:1)

您可以展平元组,然后按生成器创建列名,最后join到原始DataFrame:

#https://stackoverflow.com/a/45122198/2901002
def mygen(lst):
    for item in lst:
        yield 'l{}'.format(item)
        yield 'n{}'.format(item)

df1 = pd.DataFrame([[b for a in row for b in a] for row in df.tod])
df1.columns = list(mygen(range(1, len(df1.columns) // 2 + 1)))
print(df1)
  l1  n1    l2   n2    l3   n3    l4   n4
0  a  10     b  6.0     h  3.0     p  2.0
1  x  11     e  2.0     l  2.0  None  NaN
2  r   5     l  5.0  None  NaN  None  NaN
3  n  15  None  NaN  None  NaN  None  NaN

df = df.join(df1)
print (df)
                                 tod l1  n1    l2   n2    l3   n3    l4   n4
0  [(a, 10), (b, 6), (h, 3), (p, 2)]  a  10     b  6.0     h  3.0     p  2.0
1          [(x, 11), (e, 2), (l, 2)]  x  11     e  2.0     l  2.0  None  NaN
2                   [(r, 5), (l, 5)]  r   5     l  5.0  None  NaN  None  NaN
3                          [(n, 15)]  n  15  None  NaN  None  NaN  None  NaN

答案 1 :(得分:0)

n = max([len(row) for row in df.tod])
f = lambda l: sum(l, ()) + ('-', np.nan)*(n-len(l))
l = [list(f(row)) for row in df.tod]

ndf = pd.DataFrame(l,columns='l1   n1  l2    n2 l3    n3  l4    n4'.split())
#  l1  n1 l2   n2 l3   n3 l4   n4
#0  a  10  b  6.0  h  3.0  p  2.0
#1  x  11  e  2.0  l  2.0  -  NaN
#2  r   5  l  5.0  -  NaN  -  NaN
#3  n  15  -  NaN  -  NaN  -  NaN

df.join(ndf)
#
#                                 tod l1  n1 l2   n2 l3   n3 l4   n4
#0  [(a, 10), (b, 6), (h, 3), (p, 2)]  a  10  b  6.0  h  3.0  p  2.0
#1          [(x, 11), (e, 2), (l, 2)]  x  11  e  2.0  l  2.0  -  NaN
#2                   [(r, 5), (l, 5)]  r   5  l  5.0  -  NaN  -  NaN
#3                          [(n, 15)]  n  15  -  NaN  -  NaN  -  NaN