熊猫:当单元格内容是列表时,为列表中的每个元素创建一行。

熊猫:当单元格内容是列表时,为列表中的每个元素创建一行。

我有一个dataframe,其中一些单元格包含多个值的列表。我不想在一个单元格中存储多个值,而是展开dataframe,以便列表中的每个项都得到自己的行(在所有其他列中都有相同的值)。所以如果我有:


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.

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


慕莱坞森
浏览 589回答 3
3回答

吃鸡游戏

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]: rOut[103]:    samples  subject  trial_num0      0.10        1          11     -0.20        1          12      0.05        1          13      0.25        1          24      1.32        1          25     -0.17        1          26      0.64        1          37     -0.22        1          38     -0.71        1          39     -0.03        2          110    -0.65        2          111     0.76        2          112     1.77        2          213     0.89        2          214     0.65        2          215    -0.98        2          316     0.65        2          317    -0.30        2          3PS在这里,您可能会发现一个更通用的解决方案。一些解释: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  subject0           1        11           1        12           1        13           2        14           2        15           2        16           3        1..        ...      ...11          1        212          2        213          2        214          2        215          3        216          3        217          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  samples0           1        1    -1.041           1        1    -0.582           1        1    -1.323           2        1     0.824           2        1    -0.595           2        1    -0.346           3        1     0.25..        ...      ...      ...11          1        2     0.6812          2        2     0.5513          2        2    -0.5614          2        2     0.6515          3        2    -0.0416          3        2     0.3617          3        2    -0.31[18 rows x 3 columns]使用pd.DataFrame()[df.columns]将保证我们按原来的顺序选择列.

暮色呼如

比我预期的要长一点:>>> df                samples  subject  trial_num0  [-0.07, -2.9, -2.44]        1          11   [-1.52, -0.35, 0.1]        1          22  [-0.17, 0.57, -0.65]        1          33  [-0.82, -1.06, 0.47]        2          14   [0.79, 1.35, -0.09]        2          25   [1.17, 1.14, -1.79]        2          3>>>>>> s = df.apply(lambda x: pd.Series(x['samples']),axis=1).stack().reset_index(level=1, drop=True)>>> s.name = 'sample'>>>>>> df.drop('samples', axis=1).join(s)   subject  trial_num  sample0        1          1   -0.070        1          1   -2.900        1          1   -2.441        1          2   -1.521        1          2   -0.351        1          2    0.102        1          3   -0.172        1          3    0.572        1          3   -0.653        2          1   -0.823        2          1   -1.063        2          1    0.474        2          2    0.794        2          2    1.354        2          2   -0.095        2          3    1.175        2          3    1.145        2          3   -1.79如果需要顺序索引,可以应用reset_index(drop=True)结果。更新:>>> res = df.set_index(['subject', 'trial_num'])['samples'].apply(pd.Series).stack()>>> res = res.reset_index()>>> res.columns = ['subject','trial_num','sample_num','sample']>>> res    subject  trial_num  sample_num  sample0         1          1           0    1.891         1          1           1   -2.922         1          1           2    0.343         1          2           0    0.854         1          2           1    0.245         1          2           2    0.726         1          3           0   -0.967         1          3           1   -2.728         1          3           2   -0.119         2          1           0   -1.3310        2          1           1    3.1311        2          1           2   -0.6512        2          2           0    0.1013        2          2           1    0.6514        2          2           2    0.1515        2          3           0    0.6416        2          3           1   -0.1017        2          3           2   -0.76

慕尼黑5688855

您也可以使用pd.concat和pd.melt为此:>>> objs = [df, pd.DataFrame(df['samples'].tolist())]>>> pd.concat(objs, axis=1).drop('samples', axis=1)   subject  trial_num     0     1     20        1          1 -0.49 -1.00  0.441        1          2 -0.28  1.48  2.012        1          3 -0.52 -1.84  0.023        2          1  1.23 -1.36 -1.064        2          2  0.54  0.18  0.515        2          3 -2.18 -0.13 -1.35>>> pd.melt(_, var_name='sample_num', value_name='sample', ...         value_vars=[0, 1, 2], id_vars=['subject', 'trial_num'])    subject  trial_num sample_num  sample0         1          1          0   -0.491         1          2          0   -0.282         1          3          0   -0.523         2          1          0    1.234         2          2          0    0.545         2          3          0   -2.186         1          1          1   -1.007         1          2          1    1.488         1          3          1   -1.849         2          1          1   -1.3610        2          2          1    0.1811        2          3          1   -0.1312        1          1          2    0.4413        1          2          2    2.0114        1          3          2    0.0215        2          1          2   -1.0616        2          2          2    0.5117        2          3          2   -1.35最后,如果需要,可以根据前三列进行排序。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python