熊猫数据框:特定ID的字符串值的计数在行中

时间:2018-07-19 07:50:55

标签: python pandas numpy dataframe data-manipulation

我有以下用例:

我想创建一个数据框,其中每一行都有一列,我可以在其中查看类别中该ID(用户)的互动次数。对我来说最难的是,它们不能被重复计算,而仅其中一个类别的匹配就可以算作1。

例如,我有:

   richtingen             id   
0  Marketing, Sales       1110 
1  Marketing, Sales       1110 
2  Finance                220  
3  Marketing, Engineering 1110 
4  IT                     3300 

现在,我想创建第三行,在这里我可以看到该ID与这些类别中的任何类别进行了总计多少次交互。每个逗号都是一个单独的类别,例如:“市场营销,销售”是市场营销和销售两个类别。要获得+1,您只需要与ID相同且其中一个类别匹配的另一行进行匹配,例如对于索引0,它将为3(索引0、1和3匹配)。该示例的输出数据应为:

   richtingen             id   freq
0  Marketing, Sales       1110 3
1  Marketing, Sales       1110 3
2  Finance                220  1
3  Marketing, Engineering 1110 3
4  IT                     3300 1

对我来说,困难的部分似乎是我无法将所有类别都添加到新行中,因为那样的话,您也许会开始数倍。例如,索引0与索引1的“市场营销”和“销售”都匹配,而我只希望它加1,而不是2。

到目前为止,我的代码是:

df['freq'] = df.groupby(['id', 'richtingen'])['id'].transform('count')

这仅匹配相同的类别组合。

我尝试过的其他方法: -创建一个将所有空缺都分成一个数组的新列:

df['splitted'] = df.richtingen.apply(lambda x: str(x.split(",")))

然后计划将这段代码中的某些内容与id上的groupby结合使用,以计算每个项目为true的次数:

   if any(t < 0 for t in x):
   # do something

我也无法使它正常工作。

  • 我尝试将类别拆分为新的行或列,但是出现了重复计算的问题。

例如,使用建议的代码:

 df['richtingen'].str.split(', ',expand=True)

请给我以下内容:

           0             1       id
    0  Marketing         Sales  1110
    1  Marketing         Sales  1110
    2        dDD          None   220
    3  Marketing   Engineering  1110
    4      ddsad          None  3300

但是接下来,我将需要创建遍历每一行的代码,然后检查ID,在各列中列出值,并检查它们是否包含在其他任何列(ID相同)中,以及是否其中匹配项将1加到频率。我怀疑这段代码可以与groupby一起使用,但是不确定,也无法弄清楚。

  • (下面的Jezrael建议的解决方案): 如果需要首先按ID划分每个id的唯一类别,请按堆栈创建MultiIndex Series,最后将SeriesGroupBy.nunique与map一起用于原始DataFrame的新列。

我认为这种解决方案可能与此类似,但是目前它计算的是唯一类别的总数(而不是与类别互动的唯一次数)。例如,此处索引2的输出为2,而应为1(因为用户只与类别进行了一次交互)。

    richtingen              id     freq
 0  Marketing, Sales        1110     3
 1  Marketing, Sales        1110     3
 2  Finance, Accounting     220      2
 3  Marketing, Engineering  1110     3
 4  IT                      3300     1

希望我让自己清楚了,任何人都知道该如何解决!总共大约有13个类别,总是在一个单元格中,但用逗号分隔。

对于msr_003:

         id          richtingen         freq_x  freq_y 
         0   220    Finance, IT           0       2
         1  1110    Finance, IT           1       2
         2  1110    Marketing, Sales      2       4
         3  1110    Marketing, Sales      3       4
         4   220    Marketing             4       1
         5   220    Finance               5       2
         6  1110    Marketing, Sales      6       4
         7  3300    IT                    7       1
         8  1110    Marketing, IT         8       4

3 个答案:

答案 0 :(得分:3)

如果需要先计算id中每个split的唯一类别,请按stack创建MultiIndex Series,最后将SeriesGroupBy.nuniquemap一起用于新列DataFrame的原始版本:

s = (df.set_index('id')['richtingen']
       .str.split(', ',expand=True)
       .stack()
       .groupby(level=0)
        .nunique())
print (s)
id
220     1
1110    3
3300    1
dtype: int64

df['freq'] = df['id'].map(s)
print (df)
               richtingen    id  freq
0        Marketing, Sales  1110     3
1        Marketing, Sales  1110     3
2                 Finance   220     1
3  Marketing, Engineering  1110     3
4                      IT  3300     1

详细信息

print (df.set_index('id')['richtingen'].str.split(', ',expand=True).stack())
id     
1110  0      Marketing
      1          Sales
      0      Marketing
      1          Sales
220   0        Finance
1110  0      Marketing
      1    Engineering
3300  0             IT
dtype: object

答案 1 :(得分:0)

我不喜欢大熊猫。但我认为您可能会感到幸运,可以根据Richtingen添加13个新列,每个列包含1个类别或不包含任何类别。创建列时,可以使用dataframe.apply或类似的函数来计算值。

然后您可以通过对ORing进行操作...

答案 2 :(得分:0)

我刚刚如下修改了您的代码。

count_unique = pd.DataFrame({'richtingen' : ["Finance, IT","Finance, IT", "Marketing, Sales", "Marketing, Sales", "Marketing","Finance", "Marketing, Sales", "IT", "Marketing, IT"], 'id': [220,1110,1110, 1110,220, 220,1110,3300,1110]})
count_unique['freq'] = list(range(0,len(count_unique)))
grp = count_unique.groupby(['richtingen', 'id']).agg({'freq' : 'count' }).reset_index(level = [0,1])
pd.merge(count_unique,grp, on = ('richtingen','id'), how = 'left')