使用掩码和错误/不兼容在数据帧中进行类型转换

2024-04-30 11:17:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我有这样一个dataframe,它的元素对于那些是字符串或列表的元素我想转换成集合,对于那些没有的元素我想用一个空集来替换。你知道吗

    id  super_graph sub_graph
GO1 GO1 ['GO4', 'GO5', 'GO6', 'GO7', 'GO8', 'GO9']  GO9
GO2 GO2 ['GO4', 'GO5', 'GO6', 'GO7', 'GO8', 'GO9']  GO11
GO3 GO3 ['GO1', 'GO5', 'GO6', 'GO7', 'GO8', 'GO9']  GO12
GO4 GO4 ['GO1', 'GO6', 'GO7']   
GO5 GO5 ['GO5'] 
GO6 GO6 ['GO1', 'GO5', 'GO7', 'GO3', 'GO9'] 
GO7 GO7 ['GO2', 'GO5', 'GO6', 'GO7', 'GO8', 'GO10', 'GO11', 'GO12'] 
GO8 GO8 ['GO2', 'GO3', 'GO4', 'GO5', 'GO6', 'GO7', 'GO8', 'GO9']    
GO9 GO9     

我通过两个步骤实现了这一点:在列表中转换字符串,然后使用它们将这些列表转换为步骤:

initial_frame = count_frame.loc[:,['id', "super_graph", "sub_graph"]]#THE FRAME WHOSE EXAMPLE YOU HAVE ABOVE
initial_frame_mask =  ~initial_frame.applymap(lambda cell: isinstance(cell, list)| (cell is None))

list_frame = initial_frame.mask(initial_frame_mask,initial_frame.applymap(lambda l: [l]))
list_frame2 = list_frame.applymap(lambda l: set(l) if l is not None else {})

这里的诀窍是使用[]list构造函数(也许我不应该使用这个词,它在语言中有非常特定的含义,但我找不到更好的)而不是list(l)在list\u框架创建中,因为它们的行为不同,[]将采取这样的字符串,list()将字符串序列分解到它们的部分。你知道吗

然后我使用set()方法转换这些列表,并使用条件表达式来避免包含None(最终目标是为每一行的列添加所有三个列表(也许我可以使用更好的方法,不知道,但无论如何,我想回答下面的问题,以供个人启发)

我实际上打算一步到位,使用如下代码:

initial_frame = count_frame.loc[:,['id', "super_graph", "sub_graph"]] 
initial_frame_mask =  ~initial_frame.applymap(lambda cell: isinstance(cell, list))

list_frame = initial_frame.mask(initial_frame_mask,initial_frame.applymap(lambda l: {l}) if l is not None else {})

但是Python不会让我做我想做的事:) 实际上set()方法接受列表和字符串,其行为类似于list()方法。因此,我打算使用{}来实现这一点,但它不起作用;抛出以下异常:

list_frame = initial_frame.mask(initial_frame_mask,initial_frame.applymap(lambda l: {l} if l is not None else {}))

TypeError: ("unhashable type: 'list'", 'occurred at index super_graph')

这和你做的完全一样

In [354]: l=[1,2]
In [355]: {l}
Traceback (most recent call last):

  File "<ipython-input-355-37b01148d270>", line 1, in <module>
    {l}

TypeError: unhashable type: 'list'

因此,我相信mask方法在执行矢量化操作之后选择数据,但是因此,这触发了我实际上不应该看到的错误,因为我的初始帧掩码是经过良好裁剪的,以避免不方便的值。你知道吗

    id  super_graph sub_graph
GO1 True    False   True
GO2 True    False   True
GO3 True    False   True
GO4 True    False   False
GO5 True    False   False
GO6 True    False   False
GO7 True    False   False
GO8 True    False   False
GO9 True    False   False

所以我想知道如何在一个步骤中实现这一点(可能使用一个类似的函数,它的行为不像mask,而是避免从坏值开始,或者使用另一种方法来转换它)。 我还想知道为什么list和[]的行为如此不同,我在Python文档中没有看到任何解释这一点的内容,以及set()和{}的idem。 提前谢谢。你知道吗

Quicknote:的确:list\u frame2=list_框架.applymap(lambda l:set(l)如果l不是None-else{})将不起作用,因为它输出

id super_graph sub_graph
GO1  {GO1}       {nan}     {GO9}
GO2  {GO2}       {nan}    {GO11}
GO3  {GO3}       {nan}    {GO12}
GO4  {GO4}       {nan}     {nan}
GO5  {GO5}       {nan}     {nan}
GO6  {GO6}       {nan}     {nan}
GO7  {GO7}       {nan}     {nan}
GO8  {GO8}       {nan}     {nan}
GO9  {GO9}       {nan}     {nan}

编辑:DataFrameGenerator(但我认为剪贴板中有一个命令可以这样做,这就是为什么我一开始没有包括它,对不起

count_frame = pd.DataFrame([["GO2","GO3","GO4","GO5","GO6","GO7","GO8","GO9"],\
[["GO4", "GO5","GO6","GO7","GO8","GO9"],
["GO4", "GO5","GO6","GO7","GO8","GO9"],
["GO1", "GO5","GO6","GO7","GO8","GO9"],
["GO1", "GO6","GO7"],
["GO5"]
["GO1", "GO5","GO7","GO3","GO9"],
["GO2", "GO5","GO6","GO7","GO8","GO10","GO11", "GO12"],
["GO2", "GO3","GO4","GO5","GO6","GO7","GO8","GO9"],
],\
["GO9","GO11","GO12"]], index = ['id','super_graph','sub_graph'], columns=["GO1","GO2","GO3","GO4","GO5","GO6","GO7","GO8","GO9","]).T

Tags: falsetruenanframelistinitialgraphgo2
1条回答
网友
1楼 · 发布于 2024-04-30 11:17:49

您可以跳过掩蔽步骤,直接转到映射。你知道吗

实际上,通过介绍下面这句话,我觉得你制造了你自己的问题。你知道吗

initial_frame_mask =  ~initial_frame.applymap(lambda cell: isinstance(cell, list))

这引入了一个对所有列表都为False的掩码,因此对于super_graph的几乎所有元素,但是对其他元素所发生的事情并不是完全透明的。你知道吗

要实现您似乎想要的目标,只需一行代码:

initial_frame = count_frame.loc[:,['id', "super_graph", "sub_graph"]] 
initial_frame.applymap(lambda l: {*l} if isinstance(l, list) else {l})

编辑:如果您不希望“无”出现在您的数据帧中,您可以先用一个方便的值替换这些值。你知道吗

initial_frame.fillna('').applymap(lambda l: {*l} if isinstance(l, list) else {l})

EDIT2:获取具有唯一项的列表的黑客解决方案(也可以作为一行程序来完成,但我认为这已经足够复杂了):

initial_frame['ss'] = initial_frame.fillna('').applymap(lambda l: [*l] if isinstance(l, list) else []).values.sum(axis=1)
initial_frame['ss'].apply(lambda x: list(filter(None,{*x})))

相关问题 更多 >