我有很多数据想要在Pandas dataframe中进行结构化。但是,我需要一个多重索引格式。Pandas MultiIndex功能总是让我感到困惑,这一次也不例外。
我按照自己的想法将结构建成了一个字典,但是由于我的实际数据要大得多,所以我想使用Pandas。下面的代码是字典变量。请注意,原始数据具有更多的标签和更多的行。
原始数据包含由索引Task_n执行的任务的行,该任务由索引Participant_n的参与者执行。每一行都是一个片段。尽管原始数据没有这种区分,但我想将其添加到我的dataframe中。换句话说:
我遇到的主要问题是我不知道如何在不提前知道维度的情况下构建多索引数据框。 我不知道会有多少个任务或段落。 所以我相信我可以保留最初的字典方法中的循环结构,然后我想我必须将其附加/连接到一个初始空数据帧中,但问题是其结构必须是什么样子的。 它不能是简单的Series,因为没有考虑到多索引。 那么怎么办呢?
对于那些已经阅读到这里并想尝试的人,我认为我的原始代码大部分可以重新使用(循环和变量赋值),但它必须是DataFrame的访问器而不是字典。 一个重要的方面是:数据应该可以像常规DataFrame一样使用getter / setter轻松阅读。 例如,轻松获取参与者二,任务2,段落2等的持续时间值。但是,获取数据子集(例如,其中
我按照自己的想法将结构建成了一个字典,但是由于我的实际数据要大得多,所以我想使用Pandas。下面的代码是字典变量。请注意,原始数据具有更多的标签和更多的行。
原始数据包含由索引Task_n执行的任务的行,该任务由索引Participant_n的参与者执行。每一行都是一个片段。尽管原始数据没有这种区分,但我想将其添加到我的dataframe中。换句话说:
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
,它是一个任意的布尔标志。生成的字典看起来像这样(为节省空间未美化。如果您想检查,请在文本编辑器中打开为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
,看起来像下面的表示方式或类似的方式。(为了简单起见,我只使用了索引,而没有使用task1
或seg1
。)
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
我遇到的主要问题是我不知道如何在不提前知道维度的情况下构建多索引数据框。 我不知道会有多少个任务或段落。 所以我相信我可以保留最初的字典方法中的循环结构,然后我想我必须将其附加/连接到一个初始空数据帧中,但问题是其结构必须是什么样子的。 它不能是简单的Series,因为没有考虑到多索引。 那么怎么办呢?
对于那些已经阅读到这里并想尝试的人,我认为我的原始代码大部分可以重新使用(循环和变量赋值),但它必须是DataFrame的访问器而不是字典。 一个重要的方面是:数据应该可以像常规DataFrame一样使用getter / setter轻松阅读。 例如,轻松获取参与者二,任务2,段落2等的持续时间值。但是,获取数据子集(例如,其中
prof === 0
)也应该没有问题。