Python pandas-使用元素的计数和频率创建数据帧

Python pandas-使用元素的计数和频率创建数据帧,python,pandas,Python,Pandas,从以下数据帧开始df: df = pd.DataFrame({'node':[1,2,3,3,3,5,5],'lang':['it','en','ar','ar','es','uz','es']}) 我正在尝试构建结构: node langs lfreq 0 1 [it] [1] 1 2 [en] [1] 2 3 [ar, es] [2, 1] 3 5 [uz, es] [1, 1] 因此

从以下数据帧开始
df

df = pd.DataFrame({'node':[1,2,3,3,3,5,5],'lang':['it','en','ar','ar','es','uz','es']})
我正在尝试构建结构:

    node     langs   lfreq
0      1      [it]     [1]
1      2      [en]     [1]
2      3  [ar, es]  [2, 1]
3      5  [uz, es]  [1, 1]
因此,基本上是通过列表将每个节点的
lang
元素和频率分组到一行中。到目前为止我所做的:

# Getting the unique langs / node
a = df.groupby('node')['lang'].unique().reset_index(name='langs')

# Getting the frequency of lang / node
b = df.groupby('node')['lang'].value_counts().reset_index(name='lfreq')
c = b.groupby('node')['lfreq'].unique().reset_index(name='lfreq')
然后在
节点上进行合并

d = pd.merge(a,c,on='node')
经过这次操作,我得到的是:

    node     langs   lfreq
0      1      [it]     [1]
1      2      [en]     [1]
2      3  [ar, es]  [2, 1]
3      5  [uz, es]     [1]

您可能会注意到,最后一行只有一个
[1]
出现两个
[uz,es]
的频率,而不是预期的
[1,1]
列表。是否有一种方法可以以更简洁的方式执行分析,以获得所需的输出?

我将使用agg函数和tolist()

替换

c = b.groupby('node')['lfreq'].unique().reset_index(name='lfreq')

和中提琴:

   node     langs   lfreq
0     1      [it]     [1]
1     2      [en]     [1]
2     3  [ar, es]  [2, 1]
3     5  [uz, es]  [1, 1]
您可以使用参数
返回\u counts=True

df = pd.DataFrame({'node':[1,2,3,3,3,5,5],'lang':['it','en','ar','ar','es','uz','es']})
print df
  lang  node
0   it     1
1   en     2
2   ar     3
3   ar     3
4   es     3
5   uz     5
6   es     5

a = df.groupby('node')['lang'].apply(lambda x: np.unique(x, return_counts=True))
                              .reset_index(name='tup')

#split tuples
a[['langs','lfreq']] = a['tup'].apply(pd.Series)
#filter columns
print a[['node','langs','lfreq']]
   node     langs   lfreq
0     1      [it]     [1]
1     2      [en]     [1]
2     3  [ar, es]  [2, 1]
3     5  [es, uz]  [1, 1]

在某种程度上,因为您(在评论中)提到了速度对于拥有4000万行的重要性,所以我建议您查看以下内容

df.groupby(['node','lang'])['lang'].count()

node  lang
1     it      1
2     en      1
3     ar      2
      es      1
5     es      1
      uz      1
一般来说,使用更平坦的结构(python的zen)会更好,更具体地说,您希望pandas/numpy列是简单类型(int和float),而不是对象


考虑到groupby等pandas方法,上述结构应该比以列表形式存储更容易操作,而且几乎可以保证速度更快,可能更快。我假设您希望使用此结构进行进一步处理,但即使不使用,也可以通过这种方式将数据制成表格。

谢谢。与其他答案相比,速度如何?我知道,在一个50万行的数据帧上,应用大型数据帧(我有近4000万行)的速度很慢,@JohnE solution比dmb(64秒)和jezrael(136秒)快得多(1.5秒)。
df = pd.DataFrame({'node':[1,2,3,3,3,5,5],'lang':['it','en','ar','ar','es','uz','es']})
print df
  lang  node
0   it     1
1   en     2
2   ar     3
3   ar     3
4   es     3
5   uz     5
6   es     5

a = df.groupby('node')['lang'].apply(lambda x: np.unique(x, return_counts=True))
                              .reset_index(name='tup')

#split tuples
a[['langs','lfreq']] = a['tup'].apply(pd.Series)
#filter columns
print a[['node','langs','lfreq']]
   node     langs   lfreq
0     1      [it]     [1]
1     2      [en]     [1]
2     3  [ar, es]  [2, 1]
3     5  [es, uz]  [1, 1]
df.groupby(['node','lang'])['lang'].count()

node  lang
1     it      1
2     en      1
3     ar      2
      es      1
5     es      1
      uz      1