在每次迭代中使用 pandas 填充多个变量
Populating multiple variables in each iteration with pandas
我有许多变量,我的目的是在多次迭代中填充每个变量,而每个变量都需要不同的表达式才能提取它们的值。大致相当于我正在尝试做的是以下 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-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
但是创建具有相同列的数据框有点奇怪,没有太多信息
我们也可以用pairs
创建一个DataFrame(这将创建一个只有一行和MultiIndex列的DataFrame),repeat
它(因为我们想重复同一行3次,我们使用 Index.repeat
+ reindex
重复 3 次)。然后我们使用 reset_index
+ rename_axis
+ reset_index
来正确命名和排序“Var_1”。然后 melt
将以所需的形状传送数据。最后,我们可以使用 sort_values
+ reset_index
来获得与您构建的相同的 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'])
尝试:
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
您可以使用基于索引的解决方案:
当你有一个字典时,创建一个数据框,其中数据是值,索引是键。在您的情况下,您有元组键,因此使用索引将是 pd.MultiIndex
。此时你有 Var_2
、Var_3
和 Var_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
尝试:
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
我有许多变量,我的目的是在多次迭代中填充每个变量,而每个变量都需要不同的表达式才能提取它们的值。大致相当于我正在尝试做的是以下 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-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
但是创建具有相同列的数据框有点奇怪,没有太多信息
我们也可以用pairs
创建一个DataFrame(这将创建一个只有一行和MultiIndex列的DataFrame),repeat
它(因为我们想重复同一行3次,我们使用 Index.repeat
+ reindex
重复 3 次)。然后我们使用 reset_index
+ rename_axis
+ reset_index
来正确命名和排序“Var_1”。然后 melt
将以所需的形状传送数据。最后,我们可以使用 sort_values
+ reset_index
来获得与您构建的相同的 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'])
尝试:
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
您可以使用基于索引的解决方案:
当你有一个字典时,创建一个数据框,其中数据是值,索引是键。在您的情况下,您有元组键,因此使用索引将是 pd.MultiIndex
。此时你有 Var_2
、Var_3
和 Var_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
尝试:
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