我有以下两个输入数据帧:
df_item_in_cat
a b c d
0 A A B A
1 B B E B
2 C E F E
3 D F G G
df_charac_by_cat
cat charac
0 a 10
1 b 20
2 c 25
3 d 15
我想生成以下数据框:
df
item cat_nb sum_charac
0 A 3 45
1 B 4 70
2 C 1 10
3 D 1 10
4 E 2 45
5 F 2 45
6 G 2 40
其中:
如果需要,我可以得到意甲:
s_items
0 A
1 B
2 C
3 D
4 E
5 F
6 G
更具体地说,我有属于类别的产品,并且有与类别关联的商店。 我想根据每种产品的类别和每种商店的类别来了解每种产品在多少家商店中可用。希望很清楚..
ex :3种类别(a,b,d)的产品A在45家商店中可用,因为10 + 20 + 15 = 45
这就像excel中的“ vlookup”。
我很确定我可以通过迭代来做到这一点,但是我正在寻找一种“美丽”的解决方案。
我想向您展示一些研究,但是我真的不知道该怎么做.. 我尝试了合并或透视,但这并不是真的有用。
答案 0 :(得分:4)
您需要:
df_item_in_cat.melt().merge(df_charac_by_cat, left_on='variable', right_on='cat')\
.groupby('value')['charac'].agg(['count','sum'])
输出:
value count sum
0 A 3 45
1 B 4 70
2 C 1 10
3 D 1 10
4 E 3 60
5 F 2 45
6 G 2 40
而且,这是所有列重命名和“整理”的事情:
df_item_in_cat.melt(value_name='item').merge(df_charac_by_cat, left_on='variable', right_on='cat')\
.groupby('item')['charac'].agg(['count','sum']).reset_index()\
.rename(columns={'count':'cat_nb','sum':'sum_charac'})
输出:
item cat_nb sum_charac
0 A 3 45
1 B 4 70
2 C 1 10
3 D 1 10
4 E 3 60
5 F 2 45
6 G 2 40
答案 1 :(得分:2)
ScottBoston的答案要好得多,但我仍然很喜欢我所做的事情。
df_item_in_cat
中的值siic = df_item_in_cat.pipe(
lambda d: pd.Series(np.tile(d.columns, len(d)), d.values.ravel())
)
scbc = df_charac_by_cat.set_index(['cat']).charac
pd.concat(dict(
cat_nb=siic.groupby(level=0).count(),
sum_charac=siic.map(scbc).sum(level=0)
), axis=1, sort=True).rename_axis('item').reset_index()
item cat_nb sum_charac
0 A 3 45
1 B 4 70
2 C 1 10
3 D 1 10
4 E 3 60
5 F 2 45
6 G 2 40
答案 2 :(得分:2)
知道我来晚了,但是我也很喜欢我的解决方案;)
使用np.unique
v, _, c = np.unique(df.values, 1, return_counts=True)
产生
>>> print(v,c)
['A' 'B' 'C' 'D' 'E' 'F' 'G'], [3 4 1 1 3 2 2]
然后
dff = pd.DataFrame(dict(zip(v,c)), index=['cat_nb']).T
cat_nb
A 3
B 4
C 1
D 1
E 3
F 2
G 2
第二列比较棘手,但仍可以使用defaultdict
进行管理
x = defaultdict(set)
from collections import defaultdict
for d in df.to_dict('r'):
for k,v in d.items():
x[v].add(k)
如此
>>> x
{'A': {'a', 'b', 'd'},
'B': {'a', 'b', 'c', 'd'},
'E': {'b', 'c', 'd'},
'C': {'a'},
'F': {'b', 'c'},
'D': {'a'},
'G': {'c', 'd'}}
然后我们可以使用O(1)查询字典来映射它
d2 = df2.set_index('cat').to_dict()['charac']
s = pd.Series({k: sum(d2[v_] for v_ in v) for k,v in (x).items()})
dff.loc[:, 'f'] = s
我们有输出
cat_nb f
A 3 45
B 4 70
C 1 10
D 1 10
E 3 60
F 2 45
G 2 40