【问题标题】:Split rows into multiple rows with pandas使用熊猫将行拆分为多行
【发布时间】:2019-08-12 01:45:24
【问题描述】:

我有以下格式的数据集。它有 48 列和大约 200000 行。

slot1,slot2,slot3,slot4,slot5,slot6...,slot45,slot46,slot47,slot48
1,2,3,4,5,6,7,......,45,46,47,48
3.5,5.2,2,5.6,...............

我想将此数据集重塑为如下所示,其中 N 小于 48(可能是 24 或 12 等)列标题无关紧要。 当 N = 4

slotNew1,slotNew2,slotNew3,slotNew4
1,2,3,4
5,6,7,8
......
45,46,47,48
3.5,5.2,2,5.6
............

我可以逐行读取,然后拆分每一行并附加到一个新的数据帧。但这是非常低效的。有没有更有效、更快捷的方法来做到这一点?

【问题讨论】:

  • 每一行都是一个连接字符串吗?还是已经拆分单元格?
  • 已经拆分单元格:) 我没有拆分任何单元格。
  • N 总是 ncols 的因素吗?
  • 嗯,这不是必须的。但我可以假设 iN 是 48 的因数

标签: python pandas dataframe reshape


【解决方案1】:

你可以试试这个

N = 4
df_new = pd.DataFrame(df_original.values.reshape(-1, N))
df_new.columns = ['slotNew{:}'.format(i + 1) for i in range(N)]

代码将数据提取到numpy.ndarray,对其进行整形,并创建所需维度的新数据集。

例子:

import numpy as np
import pandas as pd

df0 = pd.DataFrame(np.arange(48 * 3).reshape(-1, 48))
df0.columns = ['slot{:}'.format(i + 1) for i in range(48)]
print(df0)
#    slot1  slot2  slot3  slot4   ...    slot45  slot46  slot47  slot48
# 0      0      1      2      3   ...        44      45      46      47
# 1     48     49     50     51   ...        92      93      94      95
# 2     96     97     98     99   ...       140     141     142     143
# 
# [3 rows x 48 columns]

N = 4
df = pd.DataFrame(df0.values.reshape(-1, N))
df.columns = ['slotNew{:}'.format(i + 1) for i in range(N)]
print(df.head())
#    slotNew1  slotNew2  slotNew3  slotNew4
# 0         0         1         2         3
# 1         4         5         6         7
# 2         8         9        10        11
# 3        12        13        14        15
# 4        16        17        18        19

另一种方法

N = 4
df1 = df0.stack().reset_index()
df1['i'] = df1['level_1'].str.replace('slot', '').astype(int) // N
df1['j'] = df1['level_1'].str.replace('slot', '').astype(int) % N
df1['i'] -= (df1['j'] == 0) - df1['level_0'] * 48 / N
df1['j'] += (df1['j'] == 0) * N
df1['j'] = 'slotNew' + df1['j'].astype(str)
df1 = df1[['i', 'j', 0]]
df = df1.pivot(index='i', columns='j', values=0)

【讨论】:

  • 这是我的错误。在重塑之前我没有删除不需要的列。当我删除不需要的列时,您的解决方案有效。谢谢(y)
【解决方案2】:

制作块后使用pandas.explode。给定df

import pandas as pd

df = pd.DataFrame([np.arange(1, 49)], columns=['slot%s' % i for i in range(1, 49)])
print(df)

   slot1  slot2  slot3  slot4  slot5  slot6  slot7  slot8  slot9  slot10  ...  \
0      1      2      3      4      5      6      7      8      9      10  ...   

   slot39  slot40  slot41  slot42  slot43  slot44  slot45  slot46  slot47  \
0      39      40      41      42      43      44      45      46      47   

   slot48  
0      48  

使用chunks进行划分:

def chunks(l, n):
    """Yield successive n-sized chunks from l.
    Source: https://stackoverflow.com/questions/312443/how-do-you-split-a-list-into-evenly-sized-chunks
    """
    n_items = len(l)
    if n_items % n:
        n_pads = n - n_items % n
    else:
        n_pads = 0
    l = l + [np.nan for _ in range(n_pads)] 
    for i in range(0, len(l), n):
        yield l[i:i + n]

N = 4
new_df = pd.DataFrame(list(df.apply(lambda x: list(chunks(list(x), N)), 1).explode()))
print(new_df)

输出:

     0   1   2   3
0    1   2   3   4
1    5   6   7   8
2    9  10  11  12
3   13  14  15  16
4   17  18  19  20
...

这种方法相对于numpy.reshape 的优势在于它可以在N 不是一个因素时处理:

N = 7
new_df = pd.DataFrame(list(df.apply(lambda x: list(chunks(list(x), N)), 1).explode()))
print(new_df)

输出:

    0   1   2   3   4   5     6
0   1   2   3   4   5   6   7.0
1   8   9  10  11  12  13  14.0
2  15  16  17  18  19  20  21.0
3  22  23  24  25  26  27  28.0
4  29  30  31  32  33  34  35.0
5  36  37  38  39  40  41  42.0
6  43  44  45  46  47  48   NaN

【讨论】:

  • 我标记了 kitman 的答案,因为当 N 是 48 的因子时它是直接的。但即使 N 不是因子,您的答案也是有效的。谢谢:)
猜你喜欢
  • 1970-01-01
  • 2020-12-26
  • 2021-12-04
  • 2016-12-03
  • 1970-01-01
  • 2018-10-17
  • 2016-08-30
  • 2022-10-17
  • 2018-11-16
相关资源
最近更新 更多