2017-09-04 33 views
0

我有这样的数据框,其元素我想要转换为那些字符串或列表的集合,并用空集替换那些是无。使用掩码和错误/不兼容的数据框中的类型转换

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_frame创建的list(l),因为它们的行为不同,[]会采用一个字符串,list()会将字符串序列分解为它们的部分。

然后,我使用set()方法和条件表达式转换这些列表以避免包含无(最终目标是为列的每一行添加所有三个列表(也许我可以使用更好的方法,不要知道,但无论如何,我要回答到的关注对象的问题,个人造就)

其实我打算做这一步,使用的代码如下:

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' 

所以我相信面具方法选择整体上进行矢量化操作之后的数据,但这样,这会触发这个错误,我实际上不应该看到,因为我的initial_frame_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 

所以我想知道我可以在一个步骤做到这一点(可能使用了类似的功能,即不表现得像面具,但要避免开始与坏的值,或用另一种方式来转换这个)。 我也想知道为什么list和[]行为如此不同,我没有看到任何Python文档解释这是有意的,同样也是set()和{}。 提前致谢。

Quicknote:确实:list_frame2 = list_frame.applymap(拉姆达升:设定(L)如果L不无其他{})将不会工作,因为它输出

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} 

编辑:数据帧生成器(但我认为这是从剪贴板中做到这一点的命令,这就是为什么我起初并不包括它,对不起;

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 
+1

你能提供生成输入的方法数据帧?目前还不清楚“dtypes”是什么。 – IanS

+1

您是否尝试过使用“{* l}”而不是“{l}”? – Uvar

+0

这将是一个很好的电话,但它会打破字符串。无论如何,我最后继续清单,然后总结这些然后转换这些集(我有一个无条件的无条件使用,如果None用{}取代无与字典,但无论如何写入如果None然后set()doesn'不会改变任何东西和总和不能很好地与设置...) –

回答

1

可以跳过掩模步骤,直接进入映射

其实。 ,通过介绍以下内容,我觉得你创造了自己的问题。

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

这引入了一个面膜哪个是假的所有列表,因此对于相当多的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:哈克解决方案,让名单与独特的项目(也可以做到这一点作为oneliner,但估计这已经是令人费解就够了):

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}))) 
+0

问题是,我不想包括无套,因为这将是繁琐的消除它们,但我想我可以实现这与initial_frame.applymap (lambda l:{* l}如果l不是其他情况无如果l isinstance(l,list)else {l})。加上无论如何,我意识到我无法总结与列表(working_series = list_frame.sum(axis = 1))的方式集合,所以我在列表中完全做到这一点,然后使用working_series.map(set)(否则我有一套只有浮动的套数,奇怪的是,对于列表来说都没问题)。无论如何,我会接受你的答案,因为你确实回答了问题 –

+1

如果你想摆脱Nones,你可以做'initial_frame.fillna('')'。至于轴1上的总和,这可能会产生可怕的结果,如'{'GO3'}'等等或者只是float64s'0'。 – Uvar

+0

是的,实际上我在None部分弄错了,我想用列表填充,但这是不可能的,所以我试图在替换它们之后替换它们(字符串替换没有发生在我身上,我对此很愚蠢,因为我无论如何替换字符串)。对于求和部分,我并没有比求和列表更好的调用,因为使用set不起作用,并且我想要灵活的地方,我不需要指定索引或标签或循环等等。所以我想用列表来看,应该没问题?每次不打开包装可能会比使用面罩的效率更低效? –

相关问题