gpt4 book ai didi

python - 将 dict 构造函数转换为 Pandas MultiIndex 数据框

转载 作者:太空狗 更新时间:2023-10-29 20:57:42 25 4
gpt4 key购买 nike

我有很多数据想在 Pandas 数据框中构建。但是,为此我需要一个多索引格式。 Pandas MultiIndex 功能一直让我感到困惑,而且这次我无法理解它。

我按照自己的意愿构建了结构,但由于我的实际数据要大得多,所以我想改用 Pandas。下面的代码是 dict 变体。请注意,原始数据有更多的标签和更多的行。

想法是,原始数据包含索引为 Task_n 的任务的行,该任务已由索引为 Participant_n 的参与者执行。每是一个段。即使原始数据没有这种区别,我也想将其添加到我的数据框中。换句话说:

Participant_n | Task_n | val | dur
----------------------------------
1 | 1 | 12 | 2
1 | 1 | 3 | 4
1 | 1 | 4 | 12
1 | 2 | 11 | 11
1 | 2 | 34 | 4

上面的例子包含一个个参与者,两个个任务,分别有三个两个个片段(行) .

在 Python 中,dict 结构看起来像这样:

import pandas as pd

cols = ['Participant_n', 'Task_n', 'val', 'dur']

data = [[1,1,25,83],
[1,1,4,68],
[1,1,9,987],
[1,2,98,98],
[1,2,84,4],
[2,1,9,21],
[2,2,15,6],
[2,2,185,6],
[2,2,18,4],
[2,3,8,12],
[3,1,7,78],
[3,1,12,88],
[3,2,12,48]]

d = pd.DataFrame(data, columns=cols)

part_d = {}
for row in d.itertuples():
participant_n = row.Participant_n
participant = "participant" + str(participant_n)
task = "task" + str(row.Task_n)

if participant in part_d:
part_d[participant]['all_sum']['val'] += int(row.val)
part_d[participant]['all_sum']['dur'] += int(row.dur)
else:
part_d[participant] = {
'prof': 0 if participant_n < 20 else 1,
'all_sum': {
'val': int(row.val),
'dur': int(row.dur),
}
}

if task in part_d[participant]:
# Get already existing keys
k = list(part_d[participant][task].keys())

k_int = []
# Only get the ints (i.e. not all_sum etc.)
for n in k:
# Get digit from e.g. seg1
n = n[3:]
try:
k_int.append(int(n))
except ValueError:
pass

# Increment max by 1
i = max(k_int) + 1
part_d[participant][task][f"seg{i}"] = {
'val': int(row.val),
'dur': int(row.dur),
}
part_d[participant][task]['task_sum']['val'] += int(row.val)
part_d[participant][task]['task_sum']['dur'] += int(row.dur)
else:
part_d[participant][task] = {
'seg1': {
'val': int(row.val),
'dur': int(row.dur),
},
'task_sum': {
'val': int(row.val),
'dur': int(row.dur),
}
}

print(part_d)

在最终结果中,我有一些额外的变量,例如:task_sum(参与者任务的总和)、all_sum(参与者所有操作的总和),以及 prof 这是任意 bool 标志。生成的字典看起来像这样(没有美化以节省空间。如果你想检查,在文本编辑器中以 JSON 或 Python 字典打开并美化):

{'participant1': {'prof': 0, 'all_sum': {'val': 220, 'dur': 1240}, 'task1': {'seg1': {'val': 25, 'dur': 83}, 'task_sum': {'val': 38, 'dur': 1138}, 'seg2': {'val': 4, 'dur': 68}, 'seg3': {'val': 9, 'dur': 987}}, 'task2': {'seg1': {'val': 98, 'dur': 98}, 'task_sum': {'val': 182, 'dur': 102}, 'seg2': {'val': 84, 'dur': 4}}}, 'participant2': {'prof': 0, 'all_sum': {'val': 235, 'dur': 49}, 'task1': {'seg1': {'val': 9, 'dur': 21}, 'task_sum': {'val': 9, 'dur': 21}}, 'task2': {'seg1': {'val': 15, 'dur': 6}, 'task_sum': {'val': 218, 'dur': 16}, 'seg2': {'val': 185, 'dur': 6}, 'seg3': {'val': 18, 'dur': 4}}, 'task3': {'seg1': {'val': 8, 'dur': 12}, 'task_sum': {'val': 8, 'dur': 12}}}, 'participant3': {'prof': 0, 'all_sum': {'val': 31, 'dur': 214}, 'task1': {'seg1': {'val': 7, 'dur': 78}, 'task_sum': {'val': 19, 'dur': 166}, 'seg2': {'val': 12, 'dur': 88}}, 'task2': {'seg1': {'val': 12, 'dur': 48}, 'task_sum': {'val': 12, 'dur': 48}}}}

我希望这不是字典,而是以具有多个索引的 pd.DataFrame 结束,看起来像下面的表示或类似的表示。 (为简单起见,我只是使用了索引,而不是 task1seg1。)

Participant   Prof all_sum      Task    Task_sum     Seg   val   dur
val dur val dur
====================================================================
participant1 0 220 1240 1 38 1138 1 25 83
2 4 68
3 9 987
2 182 102 1 98 98
2 84 4
--------------------------------------------------------------------
participant2 0 235 49 1 9 21 1 9 21
2 218 16 1 15 6
2 185 6
3 18 4
3 8 12 1 8 12
--------------------------------------------------------------------
participant3 0 31 214 1 19 166 1 7 78
2 12 88
2 12 48 1 12 48

这种结构在 Pandas 中可行吗?如果不是,有哪些合理的替代方案?

我必须再次强调,实际上有更多的数据,可能还有更多的子级别。因此,解决方案必须灵活、高效。如果它能让事情变得更简单,我愿意只在一个轴上使用多索引,并将标题更改为:

Participant  Prof  all_sum_val  all_sum_dur  Task  Task_sum_val  Task_sum_dur  Seg   

我遇到的主要问题是,如果我事先不知道维度,我不明白如何构建多索引 df。我事先不知道会有多少任务或段。所以我很确定我可以保留我最初的 dict 方法中的循环构造,我想我然后必须附加/连接到一个初始的空 DataFrame,但问题是结构有什么看起来像。它不能是一个简单的系列,因为它没有考虑多索引。那怎么办呢?

对于那些读到这里并想尝试一下的人来说,我认为我的原始代码大部分都可以重用(循环和变量赋值),但它必须代替 dict成为 DataFrame 的访问者。这是一个重要的方面:数据应该易于使用 getters/setters 读取,就像常规的 DataFrame 一样。例如。应该很容易获得参与者二、任务 2、部分 2 等的持续时间值。而且,获取数据的子集(例如 where prof === 0)应该没有问题。

最佳答案

我唯一的建议是摆脱所有字典内容。所有这些代码都可以毫不费力地用 Pandas 重写。这也可能会加快转型过程,但需要一些时间。为了在此过程中帮助您,我重写了您提供的部分。剩下的就看你了。

import pandas as pd

cols = ['Participant_n', 'Task_n', 'val', 'dur']

data = [[1,1,25,83],
[1,1,4,68],
[1,1,9,987],
[1,2,98,98],
[1,2,84,4],
[2,1,9,21],
[2,2,15,6],
[2,2,185,6],
[2,2,18,4],
[2,3,8,12],
[3,1,7,78],
[3,1,12,88],
[3,2,12,48]]

df = pd.DataFrame(data, columns=cols)
df["Task Sum val"] = df.groupby(["Participant_n","Task_n"])["val"].transform("sum")
df["Task Sum dur"] = df.groupby(["Participant_n","Task_n"])["dur"].transform("sum")
df["seg"] =df.groupby(["Participant_n","Task_n"]).cumcount() + 1
df["All Sum val"] = df.groupby("Participant_n")["val"].transform("sum")
df["All Sum dur"] = df.groupby("Participant_n")["dur"].transform("sum")
df = df.set_index(["Participant_n","All Sum val","All Sum dur","Task_n","Task Sum val","Task Sum dur"])[["seg","val","dur"]]
df = df.sort_index()
df

输出

                                                                        seg  val  dur
Participant_n All Sum val All Sum dur Task_n Task Sum val Task Sum dur
1 220 1240 1 38 1138 1 25 83
1138 2 4 68
1138 3 9 987
2 182 102 1 98 98
102 2 84 4
2 235 49 1 9 21 1 9 21
2 218 16 1 15 6
16 2 185 6
16 3 18 4
3 8 12 1 8 12
3 31 214 1 19 166 1 7 78
166 2 12 88
2 12 48 1 12 48

试着运行这段代码,让我知道你的想法。有任何问题评论。

关于python - 将 dict 构造函数转换为 Pandas MultiIndex 数据框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49131704/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com