我正在尝试根据类别或标签从Pandas数据框中生成所有数据的三元组。假设我有一个数据框,每行有一个唯一的标识符和一个类别/标签。我想要的三元组是前两个元素来自同一类别/标签,而最后一个元素来自不同类别/标签。我希望得到所有这样的三元组。
我可以很好地生成具有相同标签的元素组合,但是当我尝试用具有不同标签的元素扩展这些组合时,我得到一个充满None
的数组。
我的示例数据框如下:
import pandas as pdimport numpy as npdf = pd.DataFrame({'uuid': np.arange(5), 'label': [0, 1, 1, 0, 0]})print(df) label uuid0 0 01 1 12 1 23 0 34 0 4
请注意,uuid
列在这里只是一个占位符。关键是每行都是唯一的。以下代码生成所有具有相同元素的组合,并将它们放入一个列表中:
import itertools as itlabels = df.label.unique()all_combos = []for l in labels: combos = list(it.combinations(df.loc[df.label == l].as_matrix(), 2)) all_combos.extend([list(c) for c in combos]) # 转换为列表,因为我预计稍后需要向每个组合添加元素all_combos[[array([0, 0]), array([0, 3])], [array([0, 0]), array([0, 4])], [array([0, 3]), array([0, 4])], [array([1, 1]), array([1, 2])]]
现在,我希望所有这些组合都附加一个不同的元素。
我尝试了:
for l in labels: combos = list(it.combinations(df.loc[df.label == l].as_matrix(), 2)) combo_list = [list(c) for c in combos] for c in combo_list: new_combos = [list(c).extend(s) for s in df.loc[df.label != l].as_matrix()] all_combos.append(new_combos)
我期望得到:
all_combos[[array([0, 0]), array([0, 3]), array([1, 1])], [array([0, 0]), array([0, 3]), array([1, 2])], [array([0, 0]), array([0, 4]), array([1, 1])], [array([0, 0]), array([0, 4]), array([1, 2])], [array([0, 3]), array([0, 4]), array([1, 1])], [array([0, 3]), array([0, 4]), array([1, 2])], [array([1, 1]), array([1, 2]), array([0, 0])], [array([1, 1]), array([1, 2]), array([0, 3])], [array([1, 1]), array([1, 2]), array([0, 4])]]
我得到的却是:
all_combos[[None, None], [None, None], [None, None], [None, None, None]]
这看起来非常奇怪:它们甚至不是相同长度的!但我的结果中None
的数量确实与预期的有效三元组数量相同。
我也尝试了all_combos.extend(new_combos)
,得到一个包含9个元素的一维列表,所以只是上面结果的扁平版本。事实上,在内循环的最后两行中,list.extend
和list.append
的任何组合都会给我上面显示的结果,或者是该结果的扁平版本,这对我来说都不合理。
编辑:正如评论中提到的,list.extend
和list.append
是原地操作,因此不会返回任何东西。那么,我如何让我的列表推导式给我这些值呢?或者重构为其他有效的方法?
回答:
我已经解决了这个问题。我将它留在这里,以防其他人遇到类似的问题,但正如评论中提到的,问题在于list.append
和list.extend
是原地操作,因此即使在列表推导式中也会返回None
。
我通过使用np.concatenate
将我的数组拼接在一起来解决这个问题:
for l in labels: combos = list(it.combinations(df.loc[df.label == l].as_matrix(), 2)) for c in combos: new_combos = [np.concatenate((c, (s,)), axis=0) for s in df.loc[df.label != l].as_matrix()] all_combos.extend(new_combos)
此外,在列表推导式中使用np.append(c, (s,), axis=0)
也同样有效。