Pandas - 从列表中为每个复制复制具有新列值的行

Pandas - replicate rows with new column value from a list for each replication

所以我有一个包含两列的数据框,状态和成本,以及新的“假设”成本的单独列表

State   Cost
A       2
B       9
C       8
D       4

New_Cost_List = [1, 5, 10]

我想为 New_Cost 的每个值复制数据集中的所有行,为每个州的每个 New_Cost 添加一个新列。

State   Cost   New_Cost
A       2      1
B       9      1
C       8      1
D       4      1
A       2      5
B       9      5
C       8      5
D       4      5
A       2      10
B       9      10
C       8      10
D       4      10

我认为 for 循环可能适合迭代,根据列表的长度复制我的数据集并将列表的值添加为新列:

for v in New_Cost_List:
    df_new = pd.DataFrame(np.repeat(df.values, len(New_Cost_List), axis=0))
    df_new.columns = df.columns
    df_new['New_Cost'] = v

此输出为我提供了 State 和 Cost 的正确复制,但每行的 New_Cost 值为 10。很明显,我没有通过每个复制集的列表将如何将其获取到 运行 联系起来,所以有什么建议吗?或者有更好的方法来解决这个问题吗?

编辑 1

将 New_Cost_List 中的值数量从 4 个减少到 3 个,这样行数和列表长度就会有所不同。

如果我正确理解你的问题,这应该可以解决你的问题。

df['New Cost'] = new_cost_list
df = pd.concat([df]*len(new_cost_list), ignore_index=True)

输出:

    State   Cost    New Cost
0   A   2   1
1   B   9   5
2   C   8   10
3   D   4   15
4   A   2   1
5   B   9   5
6   C   8   10
7   D   4   15
8   A   2   1
9   B   9   5
10  C   8   10
11  D   4   15
12  A   2   1
13  B   9   5
14  C   8   10
15  D   4   15

您可以使用 index.repeat and numpy.tile:

df2 = (df
 .loc[df.index.repeat(len(New_Cost_List))]
 .assign(**{'New_Cost': np.repeat(New_Cost_List, len(df))})
)

或者,简单地说,使用 cross merge:

df2 = df.merge(pd.Series(New_Cost_List, name='New_Cost'), how='cross')

输出:

  State  Cost  New_Cost
0     A     2         1
0     A     2         5
0     A     2        10
1     B     9         1
1     B     9         5
1     B     9        10
2     C     8         1
2     C     8         5
2     C     8        10
3     D     4         1
3     D     4         5
3     D     4        10

对于提供的订单:

(df
 .merge(pd.Series(New_Cost_List, name='New_Cost'), how='cross')
 .sort_values(by='New_Cost', kind='stable')
 .reset_index(drop=True)
)

输出:

   State  Cost  New_Cost
0      A     2         1
1      B     9         1
2      C     8         1
3      D     4         1
4      A     2         5
5      B     9         5
6      C     8         5
7      D     4         5
8      A     2        10
9      B     9        10
10     C     8        10
11     D     4        10

下面是使用pd.concat()keys参数的方法:

(pd.concat([df]*len(New_Cost_List),
           keys = New_Cost_List,
           names = ['New_Cost',None])
 .reset_index(level=0))

输出:

   New_Cost State  Cost
0         1     A     2
1         1     B     9
2         1     C     8
3         1     D     4
0         5     A     2
1         5     B     9
2         5     C     8
3         5     D     4
0        10     A     2
1        10     B     9
2        10     C     8
3        10     D     4