【问题标题】:How to split column data and create new DataFrame with multiple columns如何拆分列数据并创建具有多列的新 DataFrame
【发布时间】:2018-12-10 08:09:52
【问题描述】:

我想在下面的DataFrame中拆分数据

df = pd.DataFrame(data={'per': np.repeat([10,20,30], 32), 'r':12*range(8), 'cnt': np.random.randint(300, 400, 96)}); df

    cnt  per  r
0   355   10  0
1   359   10  1
2   347   10  2
3   390   10  3
4   304   10  4
5   306   10  5
..  ...  ... ..
87  357   30  7
88  371   30  0
89  396   30  1
90  357   30  2
91  353   30  3
92  306   30  4
93  301   30  5
94  329   30  6
95  312   30  7

[96 rows x 3 columns]

这样对于每个 r 值,一个新列 cnt_r{r} 存在于 DataFrame 中,但也保留相应的 per 列。

以下代码几乎可以满足我的要求,只是它松开 per 列:

pd.DataFrame({'cnt_r{}'.format(i): df[df.r==i].reset_index()['cnt'] for i in range(8)})

   cnt_r0  cnt_r1  cnt_r2  cnt_r3  cnt_r4  cnt_r5  cnt_r6  cnt_r7
0     355     359     347     390     304     306     366     310
1     394     331     384     312     380     350     318     396
2     340     336     360     389     352     370     353     319
...
9      341     300     386     334     386     314     358     326
10     357     386     311     382     356     339     375     357
11     371     396     357     353     306     301     329     312

我需要一种方法来构建以下 DataFrame:

   per  cnt_r0  cnt_r1  cnt_r2  cnt_r3  cnt_r4  cnt_r5  cnt_r6  cnt_r7
0   10     355     359     347     390     304     306     366     310
1   10     394     331     384     312     380     350     318     396
2   10     340     336     360     389     352     370     353     319
...
7   20     384     385     376     323     345     339     339     347
9   30     341     300     386     334     386     314     358     326
10  30     357     386     311     382     356     339     375     357
11  30     371     396     357     353     306     301     329     312

请注意,通过构造,我的数据集对于每个 per 的每个 r 具有相同数量的值。显然我的数据集比示例一大得多(大约 8 亿条记录)。

非常感谢您的宝贵时间。

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    如果可能,将reshape 用于2d array,然后使用insert 新列per

    np.random.seed(1256)
    
    df = pd.DataFrame(data={'per': np.repeat([10,20,30], 32), 
                            'r': 12*list(range(8)), 
                            'cnt': np.random.randint(300, 400, 96)})
    
    
    df1 = pd.DataFrame(df['cnt'].values.reshape(-1, 8)).add_prefix('cnt_r')
    df1.insert(0, 'per', np.repeat([10,20,30], 4))
    print (df1)
        per  cnt_r0  cnt_r1  cnt_r2  cnt_r3  cnt_r4  cnt_r5  cnt_r6  cnt_r7
    0    10     365     358     305     311     393     343     340     313
    1    10     393     319     358     351     322     387     316     359
    2    10     360     301     337     333     322     337     393     396
    3    10     320     344     325     310     338     381     314     339
    4    20     323     305     342     340     343     319     332     371
    5    20     398     308     350     320     340     319     305     369
    6    20     344     340     345     332     373     334     304     331
    7    20     323     349     301     334     344     374     300     336
    8    30     357     375     396     354     309     391     304     334
    9    30     311     395     372     359     370     342     351     330
    10   30     378     302     306     341     308     392     387     332
    11   30     350     373     316     376     338     351     398     304
    

    或使用cumcount 创建新组并通过set_indexunstack 重塑:

    df = (df.set_index([df.groupby('r').cumcount(), 'per','r'])['cnt']
            .unstack()
            .add_prefix('cnt_r')
            .reset_index(level=1)
            .rename_axis(None, axis=1))
    print (df)
        per  cnt_r0  cnt_r1  cnt_r2  cnt_r3  cnt_r4  cnt_r5  cnt_r6  cnt_r7
    0    10     365     358     305     311     393     343     340     313
    1    10     393     319     358     351     322     387     316     359
    2    10     360     301     337     333     322     337     393     396
    3    10     320     344     325     310     338     381     314     339
    4    20     323     305     342     340     343     319     332     371
    5    20     398     308     350     320     340     319     305     369
    6    20     344     340     345     332     373     334     304     331
    7    20     323     349     301     334     344     374     300     336
    8    30     357     375     396     354     309     391     304     334
    9    30     311     395     372     359     370     342     351     330
    10   30     378     302     306     341     308     392     387     332
    11   30     350     373     316     376     338     351     398     304
    

    【讨论】:

    • 非常感谢您的启发性回答!我在第一个答案中遇到的问题(在我的数据集上)是插入问题。我必须使用以下代码创建perdf1.insert(0, 'per', df['per'].values.reshape(-1,8).transpose()[0]) 否则第二个解决方案就像一个魅力。
    • @Claudio - 嗯,这取决于真实数据,np.repeat 不可能使用?
    • 你太快了... :D
    • @Claudio - 好的,我可以检查第一个解决方案
    • 嗯,对我来说你的代码和类似的工作df1.insert(0, 'per', df['per'].values.reshape(-1,8)[:, [0]])
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-07
    • 2021-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多