Python-列表的pandas列,为每个列表元素创建一行

发布于 2021-02-02 23:18:11

我有一个数据框,其中某些单元格包含多个值的列表。我不想扩展一个单元格中的多个值,而是想扩展数据框,以便列表中的每个项目都有自己的行(所有其他列中的值都相同)。所以,如果我有:

import pandas as pd
import numpy as np

df = pd.DataFrame(
    {'trial_num': [1, 2, 3, 1, 2, 3],
     'subject': [1, 1, 1, 2, 2, 2],
     'samples': [list(np.random.randn(3).round(2)) for i in range(6)]
    }
)

df
Out[10]: 
                 samples  subject  trial_num
0    [0.57, -0.83, 1.44]        1          1
1    [-0.01, 1.13, 0.36]        1          2
2   [1.18, -1.46, -0.94]        1          3
3  [-0.08, -4.22, -2.05]        2          1
4     [0.72, 0.79, 0.53]        2          2
5    [0.4, -0.32, -0.13]        2          3

如何转换为长格式,例如:

   subject  trial_num  sample  sample_num
0        1          1    0.57           0
1        1          1   -0.83           1
2        1          1    1.44           2
3        1          2   -0.01           0
4        1          2    1.13           1
5        1          2    0.36           2
6        1          3    1.18           0
# etc.

索引并不重要,可以将现有的列设置为索引也可以,最后的顺序也不重要。

关注者
0
被浏览
140
1 个回答
  • 面试哥
    面试哥 2021-02-02
    为面试而生,有面试问题,就找面试哥。
    lst_col = 'samples'
    
    r = pd.DataFrame({
          col:np.repeat(df[col].values, df[lst_col].str.len())
          for col in df.columns.drop(lst_col)}
        ).assign(**{lst_col:np.concatenate(df[lst_col].values)})[df.columns]
    

    结果:

    In [103]: r
    Out[103]:
        samples  subject  trial_num
    0      0.10        1          1
    1     -0.20        1          1
    2      0.05        1          1
    3      0.25        1          2
    4      1.32        1          2
    5     -0.17        1          2
    6      0.64        1          3
    7     -0.22        1          3
    8     -0.71        1          3
    9     -0.03        2          1
    10    -0.65        2          1
    11     0.76        2          1
    12     1.77        2          2
    13     0.89        2          2
    14     0.65        2          2
    15    -0.98        2          3
    16     0.65        2          3
    17    -0.30        2          3
    

    PS 在这里你可能会发现一些通用的解决方案

    更新:一些解释:IMO了解此代码的最简单方法是尝试逐步执行它:

    在下一行中,我们将在一列N时间内重复值,其中N-是相应列表的长度:

    In [10]: np.repeat(df['trial_num'].values, df[lst_col].str.len())
    Out[10]: array([1, 1, 1, 2, 2, 2, 3, 3, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3], dtype=int64)
    

    可以对所有包含标量值的列进行概括:

    In [11]: pd.DataFrame({
        ...:           col:np.repeat(df[col].values, df[lst_col].str.len())
        ...:           for col in df.columns.drop(lst_col)}
        ...:         )
    Out[11]:
        trial_num  subject
    0           1        1
    1           1        1
    2           1        1
    3           2        1
    4           2        1
    5           2        1
    6           3        1
    ..        ...      ...
    11          1        2
    12          2        2
    13          2        2
    14          2        2
    15          3        2
    16          3        2
    17          3        2
    
    [18 rows x 2 columns]
    

    使用np.concatenate()我们可以展平列list(samples)中的所有值并获得一维向量:

    In [12]: np.concatenate(df[lst_col].values)
    Out[12]: array([-1.04, -0.58, -1.32,  0.82, -0.59, -0.34,  0.25,  2.09,  0.12,  0.83, -0.88,  0.68,  0.55, -0.56,  0.65, -0.04,  0.36, -0.31])
    

    将所有这些放在一起:

    In [13]: pd.DataFrame({
        ...:           col:np.repeat(df[col].values, df[lst_col].str.len())
        ...:           for col in df.columns.drop(lst_col)}
        ...:         ).assign(**{lst_col:np.concatenate(df[lst_col].values)})
    Out[13]:
        trial_num  subject  samples
    0           1        1    -1.04
    1           1        1    -0.58
    2           1        1    -1.32
    3           2        1     0.82
    4           2        1    -0.59
    5           2        1    -0.34
    6           3        1     0.25
    ..        ...      ...      ...
    11          1        2     0.68
    12          2        2     0.55
    13          2        2    -0.56
    14          2        2     0.65
    15          3        2    -0.04
    16          3        2     0.36
    17          3        2    -0.31
    
    [18 rows x 3 columns]
    

    使用pd.DataFrame()[df.columns]将确保我们按原始顺序选择列…



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看