【问题标题】:pandas - make a df from all possible combinations of columnspandas - 从所有可能的列组合中创建一个 df
【发布时间】:2019-03-22 12:43:20
【问题描述】:

我有这个熊猫数据框:

df = pd.DataFrame([['cat1', 1], ['cat2', 1], ['cat3', 2],
               ['cat1', 3]], columns=['category',
              'number'])

df
Out[32]: 
  category  number
0     cat1       1
1     cat2       1
2     cat3       2
3     cat1       3

第一列代表客户购买的产品类别。第二个代表与购买同一客户相关的数字。所以这个客户进行了 3 次购买。 我想重塑表格,以便让该客户在第一次购买然后第二次和第三次购买时购买的所有类别组合以及计算组合数量的新列:

      1     2     3  count
0  cat1  cat3   NaN      1
1  cat2  cat3   NaN      1
2  cat1  cat3  cat1      1
3  cat2  cat3  cat1      1 

我试着像这样旋转它:

df.pivot(columns='nb_achat', values='category')

但由于组合,它不起作用。你有办法做到这一点吗?

目标是了解客户第一次购买什么,然后第二次购买,以及有多少客户在购买 1 和 2 中购买了同一类别(例如)

编辑: 这里是结果的一个例子

result example

【问题讨论】:

  • “所有可能的列组合”是什么意思?你的意思是在示例输入中有另一行4 NaN 3
  • 对不起,我这里没有按照你的逻辑,你能详细解释一下吗
  • 这个问题需要更多细节,从你的例子中“所有可能的组合”不清楚
  • 并非如此。事实上,我在列类别、购买对象的类别和“数字”列中有购买的数量。示例:在此 df 中,客户进行了 3 次购买。第一次购买2件,第二次购买一件,第三次购买一件。我想要他购买的商品类别的组合
  • 我在帖子中添加了一些细节,是不是更清楚了?

标签: python pandas


【解决方案1】:
df = pd.DataFrame([['cat1', 1], ['cat2', 1], ['cat3', 2],
               ['cat1', 3]], columns=['category',
              'number'])

from itertools import product
result_items = []
product_numbers = df.number.sort_values().unique()
product_numbers = product_numbers[product_numbers >= 2]

# get all the combinations of results for all the product numbers
for number in product_numbers:

    purchase_history = []
    for hist in range(1, number+1):
        purchase_history.append(df.category[df.number == hist].tolist())

    for item in product(*purchase_history):

        item_store = {}
        for i in range(1, number+1):
            item_store[i] = item[i-1]

        result_items.append(item_store)

# put them all into a dataframe
results = pd.DataFrame(result_items)
results.fillna(0, inplace=True)
# get the counts of all history
results = results.groupby(results.columns.tolist()).size().reset_index(name='count')
# fix the NaN values
results.where(results!=0, np.nan, inplace=True)
print(results)

结果是:

      1     2     3  count
0  cat1  cat3   NaN      1
1  cat1  cat3  cat1      1
2  cat2  cat3   NaN      1
3  cat2  cat3  cat1      1

这个itertools 解决方案不是特别优雅。我很想看看是否有人可以在没有那个混乱的 for 循环的情况下做到这一点!

【讨论】:

  • 谢谢!这正是我想要的结果!它工作得很好,但不适用于 5000 行的 df(MemoryError)......如果有人能做到,我也很想看到其他解决方案哈哈。再次感谢:)
  • 是的,随着这些行的增加,我并不感到惊讶,这对内存来说有点沉重。我确信有更好的方法来解决这个问题,但不必经历那个循环。祝你好运
猜你喜欢
  • 2017-03-28
  • 1970-01-01
  • 2018-12-20
  • 2018-06-08
  • 2020-02-29
  • 2016-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多