熊猫爆炸避免值重复

时间:2020-11-12 13:49:30

标签: python pandas explode

我在多列中包含以下数据:

    col1             col2                       col3
123456     ['mary','ralph', ''bob']     ['bob','sam']
456789     ['george','fred', susie']  ['ralph','mary', 'bob']
789123     ['mary', bob']             ['bob']

我最终在每一列上都需要一个value_counts。为了使所有东西都脱离清单,我正在尝试爆炸。我可以将值爆炸后放入其列中,没问题。但是,那些了解explode的人知道我的value_counts会被夸大,因为将其应用于多个列时,explode会重复导致值重复

爆炸产生了这个例子,

  col1     col2     col3
123456     mary     bob
123456     mary     sam     
123456     mary     george
123456     ralph    bob
123456     ralph    sam     
123456     ralph    george...etc.

很显然,这会引发我需要的每列准确的value_counts。 我试过在每个列上循环爆炸,然后在每个列爆炸后匹配第一列和爆炸列并删除重复项,这是行不通的。一直不喜欢自己不是房间里最聪明的人(有更多的知识要学习),所以我向您提出了这个问题的熊猫大师。 (看看我在那里做了什么?)。谢谢。

预期的输出,以便我可以对除col1之外的所有列进行value_counts:

123456    mary     bob
123456   ralph     sam
123456     bob  george
456789  george   ralph
456789    fred    mary
456789   susie     bob
789123    mary     bob
789123     bob  george

6 个答案:

答案 0 :(得分:3)

IIUC,您可以#include <iostream> #include <string> #include <set> using namespace std; class Room { private: long id; float level; string name; set<Room> connectedRooms= {}; public: Room(long &id, float &level, set<Room> &connectedRooms) { this->id = id; this->level = level; this->connectedRooms = connectedRooms; } Room() = default; }; 而不是循环爆炸:

apply

对于不规则列表:

print (df.set_index("col1").apply(pd.Series.explode))

          col2    col3
col1                  
123456    mary     bob
123456   ralph     sam
123456     bob  george
456789  george   ralph
456789    fred    mary
456789   susie     bob
789123    mary     bob
789123     bob  george

或者:

s = df.set_index("col1").agg("sum").to_frame().explode(0)

print (s.groupby(level=0)[0].apply(pd.Series.value_counts))

col2  mary      2
      bob       2
      george    1
      susie     1
      ralph     1
      john      1
      fred      1
col3  bob       3
      george    2
      sam       1
      ralph     1
      mary      1
Name: 0, dtype: int64

答案 1 :(得分:3)

我要列表中元素的 value_counts ,首先需要展平该列,然后使用 value_counts 例如:

import pandas as pd
from itertools import chain

df = pd.DataFrame(data=[
    [123456, ['mary', 'ralph', 'bob'], ['bob', 'sam', 'george']],
    [456789, ['george', 'fred', 'susie'], ['ralph', 'mary', 'bob']],
    [789123, ['mary', 'bob'], ['bob', 'george']]
], columns=['col1', 'col2', 'col3'])

print(pd.Series(chain.from_iterable(df['col2'])).value_counts())

输出

mary      2
bob       2
susie     1
george    1
fred      1
ralph     1
dtype: int64

上面的结果是示例col2 value_counts

答案 2 :(得分:1)

您可以尝试:

df.melt('col1').explode('value')\ #melt col2 and col3 into one column and explode
  .groupby(['variable','value'])\ #Groupby melted columns
  .count()['col1']\ #count
  .unstack(0, fill_value=0)  #reshape to show counts per col2 and col3 by name

输出:

variable  col2  col3
value               
bob          2     3
fred         1     0
george       1     0
mary         2     1
ralph        1     1
sam          0     1
susie        1     0

答案 3 :(得分:0)

我们可以使用stack展开每个列表,然后使用cumcount创建代理索引

# if not real lists you'll need `literal_eval
from ast import literal_eval

s = df.set_index('col1').stack().map(literal_eval).explode().to_frame()
df1 = s.set_index(s.groupby(level=[0,1]).cumcount(),append=True).unstack(1).droplevel(0,1)

print(df1)
            col2    col3
col1                    
123456 0    mary     bob
       1   ralph     sam
       2     bob  george
456789 0  george   ralph
       1    fred    mary
       2   susie     bob
789123 0    mary     bob
       1     bob  george

答案 4 :(得分:0)

您可以应用一个函数,该函数接受flatten的每一列并返回该列的value_counts。然后将NaN的值替换为0,并将返回的帧强制转换为整数以整理输出:

import pandas as pd
from pandas.core.common import flatten

def nested_valuecounts(series):
    flattened = list(flatten(series))
    return pd.Series.value_counts(flattened)

out = df[["col2", "col3"]].apply(nested_valuecounts).fillna(0).astype(int)

print(out)
        col2  col3
bob        1     3
fred       1     0
george     1     2
mary       2     1
ralph      1     1
sam        0     1
susie      1     0

答案 5 :(得分:-1)

您可以在爆炸前合并各列

df['col4']=df['col2']+df['col3']
df.drop(columns = ['col2','col3'],inplace = True)

然后在'col4'上爆炸