gpt4 book ai didi

python - 如何使用 Pandas 处理行对并在没有字典的情况下保留 ID 列?

转载 作者:太空宇宙 更新时间:2023-11-03 16:31:42 24 4
gpt4 key购买 nike

我正在寻找更好的解决方案来解决我在研究中遇到的数据处理问题。我有一个 Pandas DataFrame,我试图提取组(Frame)中特定列(Z)的所有值,保留不同列(名称)给出的 ID 对。最终结果不必再是 Pandas 对象,但最好完全在 Pandas 中完成此操作。通过示例可以最清楚地了解任务。

d=[['7500', '3.2900', '0', 'apple'],['7500', '-0.3500', '1', 'orange'],['7500', '-4.1400', '2', 'orange'],['7501', '3.4625', '0', 'apple'],['7501', '-0.2275', '1', 'apple'],['7501', '-4.1175', '2', 'orange'],['7502', '3.2087', '0', 'orange'],['7502', '-0.7313', '1', 'apple'],['7502', '-4.7513', '2', 'apple']]
df=pd.DataFrame(d, columns=["Frame","Z","Order","Name"])


>>> df
Frame Z Order Name
0 7500 3.2900 0 apple
1 7500 -0.3500 1 orange
2 7500 -4.1400 2 orange
3 7501 3.4625 0 apple
4 7501 -0.2275 1 apple
5 7501 -4.1175 2 orange
6 7502 3.2087 0 orange
7 7502 -0.7313 1 apple
8 7502 -4.7513 2 apple

因此,对于每个框架组,我想根据“顺序”列采用独特的组合,因此对于框架 7500 组,这将是:

(0,1)
(0,2)
(1,2)

但请注意,每组中的行数可以在 1 到 5 之间变化,而不仅仅是 0、1、2。然后我会跟踪这些对的“名称”值,

(apple, orange)
(apple, orange)
(orange, orange)

然后我会取出这些相应对的“Z”值,如下所示:

( 3.2900, -0.3500)
( 3.2900, -4.1400)
(-0.3500, -4.1400)

现在,最后,结合这些数据,我想要基于“名称”列的每个唯一对的两个列表。在本例中,我们将这些列表称为first_vals和second_vals,但这完全是任意的,

(apple, orange)
first_vals = [3.2900, 3.2900, ...]
second_vals = [-0.3500, -4.1400, ...]

(orange, orange)
first_vals = [-0.3500, ...]
second_vals = [-4.140, ...]

这是我使用字典想出的一个解决方案。它有效,但我认为它非常丑陋,并且隐藏了字典键中的数据结构。此示例依赖于按 Order 列对组进行预排序,但这实际上没有问题。

from itertools import combinations
from collections import defaultdict

zpairs = defaultdict(list)

for name, group in df.groupby(["Frame"]):
order_pairs = combinations(range(len(group)), 2)
zvals = group["Z"].values
rowids = group["Name"].values
for pair in order_pairs:
pair_str = str(rowids[pair[0]])+"-"+str(rowids[pair[1]])
zpairs[pair_str+"-first"].append(zvals[pair[0]])
zpairs[pair_str+"-second"].append(zvals[pair[1]])

该代码的结果如下所示:

>>> dict(zpairs)

{'apple-apple-first': ['3.4625', '-0.7313'],
'apple-apple-second': ['-0.2275', '-4.7513'],
'apple-orange-first': ['3.2900', '3.2900', '3.4625', '-0.2275'],
'apple-orange-second': ['-0.3500', '-4.1400', '-4.1175', '-4.1175'],
'orange-apple-first': ['3.2087', '3.2087'],
'orange-apple-second': ['-0.7313', '-4.7513'],
'orange-orange-first': ['-0.3500'],
'orange-orange-second': ['-4.1400']}

有没有一种方法可以处理我的数据框,不依赖字典,也不使用字典键来存储数据?这实际上并不是为了提高性能,但这会很有帮助。

最佳答案

这是一个分两步完成的 pandas 方法:

  1. 获取每个框架组的名称和 Z 值对。
  2. 合并每对名称的 Z 值分量。

第 1 步

为了获取名称和 z 值对,我将编写一个辅助函数 get_group_pairs,我将在执行 groupby 时调用该函数。我正在执行与您在循环中执行的操作类似的过程,但在 DataFrame 中返回输出:

def get_group_pairs(grp):
pairs = combinations(grp.index, 2)
data = [grp.loc[p, ('Name', 'Z')].values.flatten('F') for p in pairs]
return pd.DataFrame(data, columns=['Name1', 'Name2', 'Z1', 'Z2'])

namepairs = df.groupby('Frame').apply(get_group_pairs).reset_index(level=1, drop=True)

reset_index纯粹是为了删除不必要的索引级别,以便中间输出看起来不错。如果您不关心中间输出,则没有必要。中间输出namepairs:

        Name1   Name2       Z1       Z2
Frame
7500 apple orange 3.2900 -0.3500
7500 apple orange 3.2900 -4.1400
7500 orange orange -0.3500 -4.1400
7501 apple apple 3.4625 -0.2275
7501 apple orange 3.4625 -4.1175
7501 apple orange -0.2275 -4.1175
7502 orange apple 3.2087 -0.7313
7502 orange apple 3.2087 -4.7513
7502 apple apple -0.7313 -4.7513

第 2 步

与步骤 1 中相同的辅助函数/groupby/apply 模式。本质上,我只是使用两个名称进行分组,然后将两个 Z 列转换为列表:

def merge_zpairs(grp):
data = {'Z1': grp['Z1'].tolist(), 'Z2': grp['Z2'].tolist()}
return pd.Series(data)

zpairs = namepairs.groupby(['Name1', 'Name2']).apply(merge_zpairs).reset_index()

同样,reset_index 并不是绝对必要的。如果没有它,您将得到一个由名称对组成的 MultiIndex。这将产生最终输出 zpairs:

    Name1   Name2                                 Z1                                    Z2
0 apple apple [3.4625, -0.7313] [-0.2275, -4.7513]
1 apple orange [3.2900, 3.2900, 3.4625, -0.2275] [-0.3500, -4.1400, -4.1175, -4.1175]
2 orange apple [3.2087, 3.2087] [-0.7313, -4.7513]
3 orange orange [-0.3500] [-4.1400]

组合代码

为方便起见,以下是步骤 1 和 2 中组合的代码:

def get_group_pairs(grp):
pairs = combinations(grp.index, 2)
data = [grp.loc[p, ('Name', 'Z')].values.flatten('F') for p in pairs]
return pd.DataFrame(data, columns=['Name1', 'Name2', 'Z1', 'Z2'])

def merge_zpairs(grp):
data = {'Z1': grp['Z1'].tolist(), 'Z2': grp['Z2'].tolist()}
return pd.Series(data)

namepairs = df.groupby('Frame').apply(get_group_pairs).reset_index(level=1, drop=True)
zpairs = namepairs.groupby(['Name1', 'Name2']).apply(merge_zpairs).reset_index()

获取字典

通过对步骤 2 的代码进行一些细微修改,您可以获得与您的类似的字典结构,尽管并不完全相同。本质上,不要使用 reset_index,而是使用 to_dictorient='index':

zpairs = namepairs.groupby(['Name1', 'Name2']).apply(merge_zpairs)
zpairs_dict = zpairs.to_dict(orient='index')

这会产生一个字典的字典:第一个键是一对名称,第二个键是您想要的 Z 值。例如,'apple-apple-first'的语法为:

zpairs_dict[('apple', 'apple')]['Z1']

关于python - 如何使用 Pandas 处理行对并在没有字典的情况下保留 ID 列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37554460/

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