【问题标题】:Pandas: transpose and sum by multiple columns熊猫:多列转置和求和
【发布时间】:2019-08-02 09:31:46
【问题描述】:

我有这个数据框:

test = pd.DataFrame({
    'user': [1,2,3,4,5,6,7,8,9],
    'category1': [2,4,0,9,1,4,6,0,1],
    'category2': [1,0,1,3,2,0,0,9,0],
    'topic1': [3,2,1,4,2,0,0,1,2],
    'topic2': [0,0,7,2,1,4,6,0,0],

})

    user    category1   category2   topic1  topic2
0   1       2           1           3       0
1   2       4           0           2       0
2   3       0           1           1       7
3   4       9           3           4       2
4   5       1           2           2       1
5   6       4           0           0       4
6   7       6           0           0       6
7   8       0           9           1       0
8   9       1           0           2       0

它显示了用户访问不同类别和不同主题的次数。

我需要计算访问过某个类别的用户也访问过某个主题的次数。所以输出应该是这样的:

    category    category_count  topic   topic_count
0   category1       27          topic1  13
1   category1       27          topic2  13
2   category2       16          topic1  11
3   category2       16          topic2  10

感谢您的帮助!

UPD:

我最终想出了这个解决方案,但我仍然认为应该有一个更优雅的方式......

categories = ['category1', 'category2']
topics = ['topic1', 'topic2']

l1 = []
l2 = []
l3 = []
l4 = []
for c in categories:
    for t in topics:
        l1.append(c)
        l2.append(test[c].sum())
        l3.append(t)
        l4.append(test[test[c] > 0][t].sum())

d = {'category':l1,
     'category_count':l2,
    'topic':l3,
    'topic_count':l4}

test_new = pd.DataFrame(d)
test_new

【问题讨论】:

  • topic1 应该是 15.. 不是吗?为什么要重复类别和主题的类型?
  • test.groupby('category1').topic1.sum()?

标签: python-3.x pandas group-by transpose


【解决方案1】:

MultiIndex.from_product使用MultiIndex

mux = pd.MultiIndex.from_product([['category1','category2'],
                                  ['topic1','topic2']])
print (mux)
MultiIndex(levels=[['category1', 'category2'], 
                   ['topic1', 'topic2']],
           codes=[[0, 0, 1, 1], [0, 1, 0, 1]])

然后退出 user 列 - 通过删除或删除索引:

df = test.set_index('user')
#print (df)

第一层和第二层使用DataFrame.reindex

df1 = df.reindex(mux, axis=1, level=0)
print (df1)
     category1        category2       
        topic1 topic2    topic1 topic2
user                                  
1            2      2         1      1
2            4      4         0      0
3            0      0         1      1
4            9      9         3      3
5            1      1         2      2
6            4      4         0      0
7            6      6         0      0
8            0      0         9      9
9            1      1         0      0

df2 = df.reindex(mux, axis=1, level=1)
print (df2)
     category1        category2       
        topic1 topic2    topic1 topic2
user                                  
1            3      0         3      0
2            2      0         2      0
3            1      7         1      7
4            4      2         4      2
5            2      1         2      1
6            0      4         0      4
7            0      6         0      6
8            1      0         1      0
9            2      0         2      0

categories 的可能总和值并通过 DataFrame.whereDataFrame.gtsum 过滤主题:

s1 = df1.sum().rename('category_count')
s2 = df2.where(df1.gt(0)).sum().astype(int).rename('topic_count')

最后一次加入:

df = (pd.concat([s1, s2], axis=1)
        .rename_axis(('category','topic'))
        .reset_index()
        .sort_index(axis=1))
print (df)
    category  category_count   topic  topic_count
0  category1              27  topic1           13
1  category1              27  topic2           13
2  category2              16  topic1           11
3  category2              16  topic2           10

【讨论】:

  • 我需要看的是有多少访问过category1的用户访问过topic1和有多少topic2。然后与 category2 相同。
  • @aviss - 抱歉,不明白。你能解释更多来自预期输出的数字13, 11, 10 吗?
  • 27 是用户访问 category1 的次数(category1 列的总和),13 是用户访问 topic1 的次数(column1 不为零的 topic1 列的总和)。等等。对不起,这很混乱!
  • @aviss - 现在很接近了,你能检查一下吗?
  • 是的,这确实更接近了。现在我需要另外两行 category1 & topic2 和 category2 & topic1。
猜你喜欢
  • 2022-06-14
  • 1970-01-01
  • 2019-12-27
  • 1970-01-01
  • 2019-04-12
  • 2016-11-23
  • 1970-01-01
  • 1970-01-01
  • 2018-08-20
相关资源
最近更新 更多