在每次迭代中使用panda填充多个变量



我有很多变量,我的意图是在多次迭代中填充每个变量,而每个变量都需要不同的表达式来提取它们的值。下面的for循环大致相当于我试图做的事情。

pairs = {('Ams', 'Rot') : 10, ('Del', 'Utr') : 12, ('Ams', 'Utr') : 14, ('Del', 'Rot') : 16}
var_1 = []
var_2 = []
var_3 = []
var_4 = []
for i in range(3):
for (j, k) in pairs:
var_1.append(i)
var_2.append(j)
var_3.append(k)
var_4.append(pairs[(j, k)])
df = {'Var_1' : var_1, 'Var_2' : var_2, 'Var_3' : var_3, 'Var_4' : var_4}
df = pd.DataFrame(df)
print(df)

我想要的输出:

Var_1 Var_2 Var_3  Var_4
0       0   Ams   Rot     10
1       0   Del   Utr     12
2       0   Ams   Utr     14
3       0   Del   Rot     16
4       1   Ams   Rot     10
5       1   Del   Utr     12
6       1   Ams   Utr     14
7       1   Del   Rot     16
8       2   Ams   Rot     10
9       2   Del   Utr     12
10      2   Ams   Utr     14
11      2   Del   Rot     16

然而,我很想知道是否有更有效的方法来做到这一点,尤其是使用pandas。最后,我想创建以下字典的pandas DataFrame。

您可以使用基于索引的解决方案:

当您有一个dict时,创建一个数据帧,其中数据是值,索引是键。在您的情况下,您有元组键,因此使用的索引将是pd.MultiIndex。此时,您有Var_2Var_3Var_4

棘手的部分是从这个数据帧生成Var_1。重复索引3次,然后重新索引数据帧。所有值都是重复的。因此,您有3 x(Ams,Rot,10(,3 x(Del,Utr,12(等等。现在,如果您将这些重复的行分组在一起,您可以使用cumcount来创建一个ID(0->第一个实例,1->第二个实例,…(。最后,按索引(Var_1(对数据帧进行排序,并重置它以获得预期结果。

# Part 1: create Var_2, Var_3 and Var_4
mi = pd.MultiIndex.from_tuples(pairs.keys(), names=['Var_2', 'Var_3'])
df = pd.DataFrame({'Var_4': pairs.values()}, index=mi).reset_index()
# Part 2: create Var_1
df = df.reindex(df.index.repeat(3))
df = df.set_index(df.groupby(df.columns.tolist()).cumcount().rename('Var_1')) 
.sort_index().reset_index()

输出:

>>> df
Var_1 Var_2 Var_3  Var_4
0       0   Ams   Rot     10
1       0   Del   Utr     12
2       0   Ams   Utr     14
3       0   Del   Rot     16
4       1   Ams   Rot     10
5       1   Del   Utr     12
6       1   Ams   Utr     14
7       1   Del   Rot     16
8       2   Ams   Rot     10
9       2   Del   Utr     12
10      2   Ams   Utr     14
11      2   Del   Rot     16

您只需使用dict-comprehension即可轻松设置

names = ['var_1', 'var_2', 'var_3', 'var_4']
values = {n: range(3) for n in names}
df = pd.DataFrame(values)
var_1  var_2  var_3  var_4
0      0      0      0      0
1      1      1      1      1
2      2      2      2      2

但是创建一个具有相同列的数据帧有点奇怪,因为它没有太多信息

尝试:

df = (pd.DataFrame({n: pd.Series(pairs) for n in range(3)})
.stack()
.rename_axis(["Var_2", "Var_3", "Var_1"])
.rename("Var_4")
.reset_index()
.sort_values("Var_1", ignore_index=True)
.sort_index(axis=1)
)
>>> df
Var_1 Var_2 Var_3  Var_4
0       0   Ams   Rot     10
1       0   Del   Utr     12
2       0   Ams   Utr     14
3       0   Del   Rot     16
4       1   Ams   Rot     10
5       1   Del   Utr     12
6       1   Ams   Utr     14
7       1   Del   Rot     16
8       2   Ams   Rot     10
9       2   Del   Utr     12
10      2   Ams   Utr     14
11      2   Del   Rot     16

尝试:

df = pd.concat([pd.Series(pairs, name='Var_4').to_frame()]*3, keys=range(3),
names=['Var_1', 'Var_2', 'Var_3']).reset_index()

输出:

Var_1 Var_2 Var_3  Var_4
0       0   Ams   Rot     10
1       0   Del   Utr     12
2       0   Ams   Utr     14
3       0   Del   Rot     16
4       1   Ams   Rot     10
5       1   Del   Utr     12
6       1   Ams   Utr     14
7       1   Del   Rot     16
8       2   Ams   Rot     10
9       2   Del   Utr     12
10      2   Ams   Utr     14
11      2   Del   Rot     16

我们也可以用pairs创建一个DataFrame(这将创建一个有一行和MultiIndex列的DataFrame(,repeatit(因为我们想重复同一行3次,所以我们使用Index.repeat+reindex重复3次(。然后用CCD_ 14+rename_axis+CCD_;Var_ 1";正确命名和排序。然后CCD_ 17将以期望的形状传递数据。最后,我们可以使用sort_values+reset_index来获得与您构建的DataFrame相同的DataFrame。

tmp = pd.DataFrame(pairs, index=[0])
out = (tmp.reindex(tmp.index.repeat(3))
.reset_index(drop=True)
.rename_axis('Var_1')
.reset_index()
.melt(id_vars=['Var_1'], var_name=['Var_2', 'Var_3'], value_name='Var_4')
.sort_values(by='Var_1')
.reset_index(drop=True))

输出:

Var_1 Var_2 Var_3  Var_4
0       0   Ams   Rot     10
1       0   Del   Utr     12
2       0   Ams   Utr     14
3       0   Del   Rot     16
4       1   Ams   Rot     10
5       1   Del   Utr     12
6       1   Ams   Utr     14
7       1   Del   Rot     16
8       2   Ams   Rot     10
9       2   Del   Utr     12
10      2   Ams   Utr     14
11      2   Del   Rot     16

或者你可以写一个列表理解,并用列表构建一个DataFrame。这与您现有的非常相似。唯一的区别是,它不是构建4个单独的列表,而是构建一个列表。

tmp = [[i, j, k, v] for i in range(3) for (j, k), v in pairs.items()]
df = pd.DataFrame(tmp, columns=['Var_1', 'Var_2', 'Var_3', 'Var_4'])

最新更新