【问题标题】:Use Python to Make a Matrix (Feature Matrix?)使用 Python 制作矩阵(特征矩阵?)
【发布时间】:2018-03-24 23:18:28
【问题描述】:

假设我有一个包含如下列的 excel 文件:

Name      Day of Shopping     Food bought      
 Bob       March 14, 2015           Apple            
 Bob       March 14, 2015            Pear                
 Joe       April 15, 2013           Apple             
 Bob        June 28, 2017     Pomegranite   
Jake      January 4, 2008          Orange   
Jake        April 9, 2010           Peach
 Joe     December 6, 2016          Banana

还有另一个excel文件,内容如下:

Name      Day of Shopping     Drink bought       
 Bob       March 14, 2015            Water    
 Joe       April 15, 2013            Juice    
 Bob        June 28, 2017             Soda
Jake      January 4, 2008            Water
Jake        April 9, 2010              Tea
 Joe     December 6, 2016             Soda

我想要做的是把它变成一个新的 excel 表,或者只是一个矩阵,上面写着:

Name   Apple  Pear  Pomegranite Orange Peach Banana Water Juice Soda Tea
Bob     1      1     0           0       0     0     1      0    0    0 
Joe     1      0     0           0       0     0     0      1    0    0 
Jake    0      0     0           1       0     0     1      0    0    0 

所以最后我得到了一个包含名称的矩阵,以下列列出了食物选项和分配名称的值(1 或 0)用于确定该项目是否是为此购买的天。请注意,在我上面描述的矩阵中,即使每个人的初始日期不同,也只找到了第一个日期的值。更多列将描述其他日期。

请帮忙。

【问题讨论】:

  • “excel 文件”是什么意思?比如,.xls 文件,还是只是一个 csv?
  • 我的意思是它包含在 .xlsx 中,但我可以将其保存为 .xls 或 csv

标签: python excel pandas dataframe feature-extraction


【解决方案1】:

您可以使用pd.crosstab 来执行此操作。假设您将数据加载到 pandas 中,并将数据框命名为 df1df2。首先将Food boughtDrink bought 两列重命名为相似的名称(我选择了Item)以轻松连接值

df1.rename(columns={'Food bought':'Item'},inplace=True)
df2.rename(columns={'Drink bought':'Item'},inplace=True)
df = pd.concat([df1,df2])

然后计算交叉表

pd.crosstab(df.Name,df.Item)

哪个会输出

Item  Apple  Banana  Juice  Orange  Peach  Pear  Pomegranite  Soda  Tea  Water
Name                                                                          
Bob       1       0      0       0      0     1            1     1    0      1
Jake      0       0      0       1      1     0            0     0    1      1
Joe       1       1      1       0      0     0            0     1    0      0

更进一步,您可以计算按日期分组的交叉表。要在 pandas 中执行此操作,我们需要将 Day of Shopping 转换为日期时间对象

df['Day of Shopping'] = pd.to_datetime(df['Day of Shopping'])

现在只需将此信息添加到pd.crosstab

pd.crosstab([df['Day of Shopping'],df.Name],df.Item)

Item                  Apple  Banana  Juice  Orange  Peach  Pear  Pomegranite  \
Day of Shopping Name                                                           
2008-01-04      Jake      0       0      0       1      0     0            0   
2010-04-09      Jake      0       0      0       0      1     0            0   
2013-04-15      Joe       1       0      1       0      0     0            0   
2015-03-14      Bob       1       0      0       0      0     1            0   
2016-12-06      Joe       0       1      0       0      0     0            0   
2017-06-28      Bob       0       0      0       0      0     0            1   
Item                  Soda  Tea  Water  
Day of Shopping Name                    
2008-01-04      Jake     0    0      1  
2010-04-09      Jake     0    1      0  
2013-04-15      Joe      0    0      0  
2015-03-14      Bob      0    0      1  
2016-12-06      Joe      1    0      0  
2017-06-28      Bob      1    0      0  

【讨论】:

  • 几个问题。由于列表很大,我只想看看至少购物过 4 次的人。有没有办法做到这一点,然后只看前三个购物日期?还有没有办法让日期而不是单独的行,只是在新列中的同一行?
  • 我个人很难你这些子问题的所有答案,特别是因为你没有提供你试图用来解决原始问题中的问题的代码。 SO 是一个一问一答的网站。你所问的问题可以通过浏览这个网站找到,这将有助于提高你对 pandas 的理解。我认为这个答案为您的其他问题提供了一个很好的起点,同时直接回答您的初始问题
【解决方案2】:

在读取您的 Excel 表格方面,您可以将它们导出为 CSV 文件并使用 Python 的 CSV Parser 从表格中读取您的值。就个人而言,我会使用来自collections 模块的默认字典。这允许您为字典键设置默认值。您可以为您拥有的每个唯一名称创建一个默认值为 0 的默认字典,并且当他们购买新产品时,将其值增加 1。要创建输出,您遍历每个客户,然后遍历他们可以购买的产品列表——因为它是一个默认值为 0 的默认字典,所以您不会遇到键不匹配的问题。

粗略的示例代码:

from collections import defaultdict

customers = {}

# Name represents the first column of your CSV entries, and product is the third column
for entry in csvdata:
    name = entry[0]
    if name not in customers:
        customers[name] = defaultdict(int) # Sets the default value to zero
    product = entry[2]
    customers[name][product] += 1

# Now you have a dictionary with customers as sub-dictionaries
# Each sub-dictionary has the count for each product

product_list = ["apples", "oranges", "pears"]

for customer, purchases in customers.items():
    for product in product_list:
        print(purchases[product])

【讨论】:

  • 如果我个人不知道所有“名称”,这可能吗?该文件实际上非常大(大约 70,000 个名称,其中一些是重复值),其中每个名称还列出了一天的购物和购买的物品。我想如果名称和日期的值重复(例如,如果 Bob 和 March 14 在列表中出现两次),Bob 只出现在新矩阵中一次,并且他当天购买的多个项目存储为 1他们各自的列。
  • if name not in customers 检查客户是否已经在客户字典中。因此,即使有两个名为“Bob”的条目,他们的购买也会被视为一个。
  • 这太不可思议了。几个问题。由于列表非常大,我只想看看至少购物过 4 次的人。此外,我想制作矩阵,以便您在第 1 列中列出名称,如果他们购买了食物,第 2-7 列将列出 1 或 0,如果他们购买了饮料,第 8-11 列将列出 1 或 0,然后第 12 - 17 列将与 2-7 相同,但对于日期 #2,18-21 与 8-11 相同,但对于日期 #2,22 - 27 对于日期 #3,28-31 对于日期 #3 .
【解决方案3】:

假设您在名为df1 的数据框中有第一个电子表格,而在df2 中有第二个电子表格,那么正确的做法是:

import pandas as pd
df = pd.concat([df1, df2])
pd.get_dummies(df, columns=['Food bought'], 'Drink bought']).groupby('Name').sum()

说明:先用pd.concat将两张表垂直合并。然后,使用pd.get_dummies 对“购买”列中的值进行一次热编码——这将为找到的每个独特的食物和饮料添加一列,当该行包含该值时为 1(因此每行只有一个 1 )。然后将groupby“姓名”浓缩成姓名,最后取每个人的sum,将每个人购买的物品总数汇总为一行。

要将excel文件读入python,请使用pd.read_excel

【讨论】:

  • 我对此有一些快速的问题。对于两个大的 excel 文件,我不确切知道框架的方向是否相同,即一个中与 Bob 有关的行是否与另一个中的 Bob 或 Joe 有关。这会造成任何并发症吗?另外我希望这些列按购物日分组(因此,如果 Bob 在 3 月去购物,他所有购买的物品将被标记为 1,然后当他在 6 月购物时,他所有购买的物品将被标记为 1 在一组新的列。
  • 你不需要担心行的顺序,如果那是你所要求的。
  • 太棒了。还有购物那天呢。我想更详细地说,我想制作矩阵,以便您在第 1 列中列出名称,第 2-7 列将列出 1 或 0,如果他们购买了食物,第 8-11 列将列出 1 或 0,如果他们买了饮料,然后第 12 - 17 列将与 2-7 相同,但日期 #2,18-21 与 8-11 相同,但日期 #2,22 - 27 用于日期 #3,以及 28- 31 代表日期#3
猜你喜欢
  • 1970-01-01
  • 2018-07-10
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
  • 2011-09-29
  • 1970-01-01
  • 2013-09-25
  • 1970-01-01
相关资源
最近更新 更多