首页 > 解决方案 > 循环为给定的数字范围创建一个新行

问题描述

我确信这是一个简单的解决方案,但我无法找到解决问题的确切方法。我的数据集有一个名为“LANE”的列,其中包含唯一值。我想根据数字范围(从 0 到 12)为每个“车道”添加行。结果,每个“LANE”将有 13 行,其中新列“NUMBER”的范围从 0 到 12,包括 12。

例子:

输入

LANE
a
b

输出

LANE    NUMBER
a       0
a       1
a       2
a       3
a       4
a       5
a       6
a       7
a       8
a       9
a       10
a       11
a       12
b       0
b       1
b       2
b       3
b       4
b       5
b       6
b       7
b       8
b       9
b       10
b       11
b       12

我目前正在尝试不同的形式:

num = 0

while num <= 12:
    for x in df['LANE']:
        df['NUMBER'] = num
    num += 1

这个循环的问题是,每个车道我仍然有一个记录,并且“NUMBER”列的值只有 12。

标签: pythonpandasloops

解决方案


理解

For 循环是生成笛卡尔积的自然而幼稚的方法。理解使我们能够更简洁地嵌入这一点。

pd.DataFrame(
    [[l, n] for l in df.LANE for n in range(12)],
    columns=['LANE', 'NUMBER']
)

   LANE  NUMBER
0     a       0
1     a       1
2     a       2
3     a       3
4     a       4
5     a       5
6     a       6
7     a       7
8     a       8
9     a       9
10    a      10
11    a      11
12    b       0
13    b       1
14    b       2
15    b       3
16    b       4
17    b       5
18    b       6
19    b       7
20    b       8
21    b       9
22    b      10
23    b      11

itertools.product

此逻辑与 Comprehension 解决方案几乎相同,但它使用itertools内置product函数。 product是一个迭代器,每次弹出一个组合。*我通过像这样打开 splat 来强制结果[*product(a, b)]pd.DataFrame最终,它是以与上述理解解决方案相同的方式传递给构造函数的列表列表。

from itertools import product

pd.DataFrame([*product(df.LANE, range(12))], columns=['LANE', 'NUMBER'])

groupby/cumcountrepeat

我不喜欢这个答案,但它为其他答案的简单性提供了一些视角。

我使用repeat复制每个索引值 12 次。我在 a 中使用这个重复的索引,loc它返回一个使用传递索引切片的数据帧。然后,我使用groupbyscumcount计算组中的每个位置并将其添加为新列。

df.loc[df.index.repeat(12)].assign(NUMBER=lambda d: d.groupby('LANE').cumcount())

  LANE  NUMBER
0    a       0
0    a       1
0    a       2
0    a       3
0    a       4
0    a       5
0    a       6
0    a       7
0    a       8
0    a       9
0    a      10
0    a      11
1    b       0
1    b       1
1    b       2
1    b       3
1    b       4
1    b       5
1    b       6
1    b       7
1    b       8
1    b       9
1    b      10
1    b      11

推荐阅读