使用 itertools.groupby() 和 recarray 的频率计数
Frequency count using itertools.groupby() with recarray
代码是这样的:
>>>data = pd.DataFrame({'P': ['p1', 'p1', 'p2'],
'Q': ['q1', 'q2', 'q1'],
'R': ['r1', 'r1', 'r2']})
>>>data
P Q R
0 p1 q1 r1
1 p1 q2 r1
2 p2 q1 r2
>>>data.groupby(['R'] + ['P','Q']).size().unstack(['P','Q'])
重建索引和 fillna(0) 后得到以下结果:
P p1 p2
Q q1 q2 q1 q2
R
r1 1 1 0 0
r2 0 0 1 0
我想对 recarray 做同样的事情,所以我导入了 itertools 并尝试了以下操作:
>>>data = np.array([('p1', 'p1', 'p2'), ('q1', 'q2', 'q1'), ('r1', 'r1', 'r2')],
dtype=[('P',object),('Q',object),('R',object)]).view(np.recarray)
>>>groupby(data,key = (['R']+['P','Q'])).size().unstack(['P','Q'])
没用。如何在不使用 pandas 的情况下获得类似的结果?
让我们远离花哨的 recarray 和对象类型。它没有给我们买任何东西。
数据可以是一个简单的二维字符串数组:
In [711]: data = np.array([('p1', 'p1', 'p2'), ('q1', 'q2', 'q1'), ('r1', 'r1', 'r2')])
In [712]: data
Out[712]:
array([['p1', 'p1', 'p2'],
['q1', 'q2', 'q1'],
['r1', 'r1', 'r2']],
dtype='<U2')
更好的是,将其设为列表列表:
In [713]: data.tolist()
Out[713]: [['p1', 'p1', 'p2'], ['q1', 'q2', 'q1'], ['r1', 'r1', 'r2']]
intertools.group
旨在与列表一起使用。它可以对数组进行操作,因为它可以对数组进行迭代。
说明您希望如何对这些字符串进行分组。
pandas group by 表达式不是自我解释的。
如果我简单地展平 data
数组,我可以将顺序值分组并计算它们:
In [726]: data.ravel()
Out[726]:
array(['p1', 'p1', 'p2', 'q1', 'q2', 'q1', 'r1', 'r1', 'r2'],
dtype='<U2')
In [727]: g=itertools.groupby(data.ravel())
In [728]: [(k,list(v)) for k,v in g]
Out[728]:
[('p1', ['p1', 'p1']),
('p2', ['p2']),
('q1', ['q1']),
('q2', ['q2']),
('q1', ['q1']),
('r1', ['r1', 'r1']),
('r2', ['r2'])]
In [729]: g=itertools.groupby(data.ravel())
In [730]: [(k,len(list(v))) for k,v in g]
Out[730]: [('p1', 2), ('p2', 1), ('q1', 1), ('q2', 1), ('q1', 1), ('r1', 2), ('r2', 1)]
=============
将我的答案扩展到工作中row-wise
In [738]: grps = [itertools.groupby(row) for row in data]
In [739]: [[(k, len(list(v))) for k,v in r] for r in grps]
[[('p1', 2), ('p2', 1)],
[('q1', 1), ('q2', 1), ('q1', 1)],
[('r1', 2), ('r2', 1)]]
这也适用于 data
的对象重载版本。
糟糕 - 我误解了您的 'row-wise' 描述。即使重读你最后的评论,我也不明白你想要什么。这听起来根本不像是 itertools.groupby
问题。我以为你在数 'r1' 和 'q2' 这样的字符串。显然不是这样。
====================
好的,更专注地尝试重新创建 pandas table
使用itertools.product
生成这6个字符串的8种组合:
In [847]: pos = list(product(['r1','r2'],['p1','p2'],['q1','q2']))
In [848]: pos
Out[848]:
[('r1', 'p1', 'q1'),
('r1', 'p1', 'q2'),
('r1', 'p2', 'q1'),
('r1', 'p2', 'q2'),
('r2', 'p1', 'q1'),
('r2', 'p1', 'q2'),
('r2', 'p2', 'q1'),
('r2', 'p2', 'q2')]
将数据帧转换为列表列表:
In [849]: val=data.values[:,[2,0,1]].tolist()
In [850]: val
Out[850]: [['r1', 'p1', 'q1'], ['r1', 'p1', 'q2'], ['r2', 'p2', 'q1']]
找出在vals
中找到哪些可能的组合:
In [852]: [[i, list(i) in val] for i in pos]
Out[852]:
[[('r1', 'p1', 'q1'), True],
[('r1', 'p1', 'q2'), True],
[('r1', 'p2', 'q1'), False],
[('r1', 'p2', 'q2'), False],
[('r2', 'p1', 'q1'), False],
[('r2', 'p1', 'q2'), False],
[('r2', 'p2', 'q1'), True],
[('r2', 'p2', 'q2'), False]]
将 'counts' 重做为 2x8 0/1 数组:
In [853]: np.array([[list(i) in val] for i in pos]).reshape(2,-1).astype(int)
Out[853]:
array([[1, 1, 0, 0],
[0, 0, 1, 0]])
代码是这样的:
>>>data = pd.DataFrame({'P': ['p1', 'p1', 'p2'],
'Q': ['q1', 'q2', 'q1'],
'R': ['r1', 'r1', 'r2']})
>>>data
P Q R
0 p1 q1 r1
1 p1 q2 r1
2 p2 q1 r2
>>>data.groupby(['R'] + ['P','Q']).size().unstack(['P','Q'])
重建索引和 fillna(0) 后得到以下结果:
P p1 p2
Q q1 q2 q1 q2
R
r1 1 1 0 0
r2 0 0 1 0
我想对 recarray 做同样的事情,所以我导入了 itertools 并尝试了以下操作:
>>>data = np.array([('p1', 'p1', 'p2'), ('q1', 'q2', 'q1'), ('r1', 'r1', 'r2')],
dtype=[('P',object),('Q',object),('R',object)]).view(np.recarray)
>>>groupby(data,key = (['R']+['P','Q'])).size().unstack(['P','Q'])
没用。如何在不使用 pandas 的情况下获得类似的结果?
让我们远离花哨的 recarray 和对象类型。它没有给我们买任何东西。
数据可以是一个简单的二维字符串数组:
In [711]: data = np.array([('p1', 'p1', 'p2'), ('q1', 'q2', 'q1'), ('r1', 'r1', 'r2')])
In [712]: data
Out[712]:
array([['p1', 'p1', 'p2'],
['q1', 'q2', 'q1'],
['r1', 'r1', 'r2']],
dtype='<U2')
更好的是,将其设为列表列表:
In [713]: data.tolist()
Out[713]: [['p1', 'p1', 'p2'], ['q1', 'q2', 'q1'], ['r1', 'r1', 'r2']]
intertools.group
旨在与列表一起使用。它可以对数组进行操作,因为它可以对数组进行迭代。
说明您希望如何对这些字符串进行分组。
pandas group by 表达式不是自我解释的。
如果我简单地展平 data
数组,我可以将顺序值分组并计算它们:
In [726]: data.ravel()
Out[726]:
array(['p1', 'p1', 'p2', 'q1', 'q2', 'q1', 'r1', 'r1', 'r2'],
dtype='<U2')
In [727]: g=itertools.groupby(data.ravel())
In [728]: [(k,list(v)) for k,v in g]
Out[728]:
[('p1', ['p1', 'p1']),
('p2', ['p2']),
('q1', ['q1']),
('q2', ['q2']),
('q1', ['q1']),
('r1', ['r1', 'r1']),
('r2', ['r2'])]
In [729]: g=itertools.groupby(data.ravel())
In [730]: [(k,len(list(v))) for k,v in g]
Out[730]: [('p1', 2), ('p2', 1), ('q1', 1), ('q2', 1), ('q1', 1), ('r1', 2), ('r2', 1)]
=============
将我的答案扩展到工作中row-wise
In [738]: grps = [itertools.groupby(row) for row in data]
In [739]: [[(k, len(list(v))) for k,v in r] for r in grps]
[[('p1', 2), ('p2', 1)],
[('q1', 1), ('q2', 1), ('q1', 1)],
[('r1', 2), ('r2', 1)]]
这也适用于 data
的对象重载版本。
糟糕 - 我误解了您的 'row-wise' 描述。即使重读你最后的评论,我也不明白你想要什么。这听起来根本不像是 itertools.groupby
问题。我以为你在数 'r1' 和 'q2' 这样的字符串。显然不是这样。
====================
好的,更专注地尝试重新创建 pandas table
使用itertools.product
生成这6个字符串的8种组合:
In [847]: pos = list(product(['r1','r2'],['p1','p2'],['q1','q2']))
In [848]: pos
Out[848]:
[('r1', 'p1', 'q1'),
('r1', 'p1', 'q2'),
('r1', 'p2', 'q1'),
('r1', 'p2', 'q2'),
('r2', 'p1', 'q1'),
('r2', 'p1', 'q2'),
('r2', 'p2', 'q1'),
('r2', 'p2', 'q2')]
将数据帧转换为列表列表:
In [849]: val=data.values[:,[2,0,1]].tolist()
In [850]: val
Out[850]: [['r1', 'p1', 'q1'], ['r1', 'p1', 'q2'], ['r2', 'p2', 'q1']]
找出在vals
中找到哪些可能的组合:
In [852]: [[i, list(i) in val] for i in pos]
Out[852]:
[[('r1', 'p1', 'q1'), True],
[('r1', 'p1', 'q2'), True],
[('r1', 'p2', 'q1'), False],
[('r1', 'p2', 'q2'), False],
[('r2', 'p1', 'q1'), False],
[('r2', 'p1', 'q2'), False],
[('r2', 'p2', 'q1'), True],
[('r2', 'p2', 'q2'), False]]
将 'counts' 重做为 2x8 0/1 数组:
In [853]: np.array([[list(i) in val] for i in pos]).reshape(2,-1).astype(int)
Out[853]:
array([[1, 1, 0, 0],
[0, 0, 1, 0]])