Python求多行数据中出现次数最多的元素及次数(按日期)

这段代码展示了如何使用Python的pandas和numpy库处理商品销售数据,目的是找出每天最热销的商品及其销售次数。首先,读取CSV文件并处理时间列,确保日期格式统一。接着,利用Counter计算每天的销售记录数。然后,通过循环遍历每一天的数据,使用bincount函数找出每天商品标签出现的次数,并确定最常见的商品标签及其出现次数。最后,将结果分别存储到result1和result2列表中,分别对应最热销商品和其销售次数。

问题描述:

表格中存在每一天每时段的商品热销记录,目前需要求出每一天最热销的商品是什么?以及它一天中热销的次数。 

表格形式:

时间商品标签
2021-12-11 9:095
2021/12/11 10:096
2021-12-12 12:106

完整版代码:

import pandas as pd
import numpy as np
import datetime as dt
from collections import Counter


df = pd.read_csv(r'C:\Users\hanhan\PycharmProjects\pythonProject\data.csv',encoding = 'gb2312', usecols=['商品标签','时间'])
time = []

for i in range(len(df)):
    starttime = df['时间'].iloc[i]
    #转换成Y-m-d H:M 字符串形式
    try:
        starttime = str(dt.datetime.strptime(starttime, '%Y-%m-%d %H:%M'))[:-3]
    except:
        starttime = str(dt.datetime.strptime(starttime, '%Y/%m/%d %H:%M'))[:-3]
    #将月-日存入time空列表中
    time.append(starttime[6:10])

print('Counter(time)',Counter(time))
day = list(Counter(time).keys())
print('day',day)
amount = list(Counter(time).values())
print('每个商品标签数量',amount)

result1 = []
result2 = []
time1 = np.array(time)
tmp = 0
for j in range(len(day)):
    # print(day[j])
    list = np.argwhere(time1==day[j])
    tmp = tmp + list.shape[0]
    commodity = df['商品标签'].iloc[list[0][0]:tmp].values
    count = np.bincount(commodity)
    common_value = np.argmax(count)
    print('出现最多次数的商品标签',common_value)
    result1.append(common_value)
    commodity_max = max(count)
    print('最多出现商品标签的次数',commodity_max)
    result2.append(commodity_max)

求解步骤:

(1)导入库

import pandas as pd
import numpy as np
import datetime as dt
from collections import Counter

(2)读取数据

df = pd.read_csv(r'C:\Users\hanhan\PycharmProjects\pythonProject\data.csv',encoding = 'gb2312', usecols=['商品标签','时间'])

        另外设置一个空列表time = []存入日期。

(3)循环遍历时间列

        处理两种不同格式的时间,利用try...expect...语句统一成一个格式,如果有个位数的时钟数或者月份数,也统一填充了,方便后面按位数取数。

        将处理好的时间格式存入time列表中,利用Counter()函数遍历一个数组内的所有元素,将元素出现的次数记下来。可以看到打印它出现的格式为:元素+元素出现次数。

         这个元素就是我们每一天的日期,元素出现次数就表示该天一共统计了几次热销商品,也就是一共多少行数据。

(4)每一天的数据分别求解出现次数最多的元素,及其出现次数

result1 = []
result2 = []

        result1是为了存入出现最多次数的元素,result2是为了存入最多出现元素的次数。


for j in range(len(day)):
    # print(day[j])
    list = np.argwhere(time1==day[j])

        找到每天多行数据在表格中的位置。

tmp = tmp + list.shape[0]

commodity = df['商品标签'].iloc[list[0][0]:tmp].values

        list.shape[0]即为每一天数据的长度,也就是多少行。用tmp临时变量存储,例如第一天数据达56行,第二天数据达100行,所以取第二天的时候,list[0][0]为56,tmp为56+100。


    count = np.bincount(commodity)
    common_value = np.argmax(count)
    print('出现最多次数的商品标签',common_value)
    result1.append(common_value)

        np.bincount()函数我理解的就是它会按照从0开始的顺序记录该数字在你的数组中出现的次数。 

        例如:x = np.array([0,1,1,2,3,4,7,7,7,8,9])

                   y = np.bincount(x)

         即,数字0出现1次,数字1出现2次,数字3出现1次...

         所以,通过argmax()函数返回array中数值最大数的下标,找出count里面的最大数的下标,其实就是那个出现最多次数的元素。


    commodity_max = max(count)
    print('最多出现商品标签的次数',commodity_max)
    result2.append(commodity_max)

        从count里面取最大数就好了,也就是出现最多的元素的次数。

<think> 我们参考了用户提供的多个引用,特别是引用[2]和引用[3]中关于DataFrame一行转多行的方法。 用户需:将一行数据转换为多行数据。在引用[2]中,我们看到有两种方法: 方法一:使用split和explode(通过concat和Series实现,但引用[2]中实际代码是concat+Series,而pandas有直接explode方法) 方法二:使用numpy进行高效处理(适用于大数据量) 另外,在引用[3]中,也提到了类似的需:将一行中某个字段(列表形式)拆分成多行,同时复制其他字段。 实际上,在pandas中,我们可以使用`explode`方法(自pandas 0.25.0版本引入)来轻松实现一行转多行。但是,如果拆分的是多个列,则需要注意。 根据用户的问题,我们主要考虑以下两种情况: 1. 单个列拆分:例如,某一列是逗号分隔的字符串,我们希望拆分成多行,其他列复制。 2. 多个列同时拆分:例如,一行中有多个列都需要拆分,且这些列拆分的长度相同(一一对应)。 我们分别说明: 情况1:单个列拆分(最简单情况) 步骤: a. 将需要拆分的列转换为列表(如果是字符串,则使用split拆分) b. 使用explode方法 情况2:多个列同时拆分(较少见,但引用[2]中方法二可以处理,但通常我们会使用explode多个列,但要每个列表长度相同) 考虑到用户需可能为情况1,我们重点介绍情况1。 另外,引用[4]中提到了使用melt方法,但melt是用于将宽格式转为长格式(列转行,但并不是拆分一个字段为多个值),所以不适用于这里的拆分。 因此,我们给出以下方法: 方法一(推荐):使用pandas的explode方法(适用于单个列拆分) 步骤: 1. 将需要拆分的列(字符串)拆分成列表(使用str.split) 2. 使用explode方法将该列爆炸成多行,其他列自动复制 示例代码(基于引用[2]的数据): 处理前: var1 var2 a,b,c 1 d,e 2 代码: import pandas as pd df = pd.DataFrame([{'var1': 'a,b,c', 'var2': 1}, {'var1': 'd,e', 'var2': 2}]) # 将var1列拆分成列表 df['var1'] = df['var1'].str.split(',') # 使用explode df = df.explode('var1') 结果: var1 var2 a 1 b 1 c 1 d 2 e 2 方法二:使用split+explode组合(同上,但可以一步完成,但实际还是两步) df = df.assign(var1=df['var1'].str.split(',')).explode('var1') 方法三:如果拆分多个列(要每个拆分的列都是列表,且每行列表长度相同) df = df.explode(['var1', 'var2']) # 但是注意,如果多个列同时拆分,那么这些列在每一行的列表长度必须相同,否则会报错 方法四:引用[2]中的方法一(使用concat+Series,但代码较长,不推荐,因为现在有了explode) 方法五:引用[2]中的方法二(使用numpy,适用于大数据量性能要高的场景) 我们主要推荐使用explode方法,因为它简洁直观。 另外,引用[3]中给出的示例也是使用explode方法(虽然没有直接写,但实际pandas支持): # 引用[3]的示例数据 data = { '姓名': ['张三'], '日期': ['2023-10-01'], '产品': [['A', 'B', 'C']], '销售额': [1500] } df = pd.DataFrame(data) # 直接使用explode拆分产品列 df = df.explode('产品') 结果:姓名和日期保持不变,产品列拆分成三行,每个产品一行,销售额重复三次。 注意:如果拆分的是字符串,需要先转换成列表(使用split),如果已经是列表则可以直接explode。 因此,针对用户的需,我们总结如下: 实现方法: 1. 如果数据中需要拆分的列是字符串(用分隔符分隔),则先使用`.str.split(分隔符)`将其转换为列表。 2. 使用`df.explode(列名)`将该列拆分成多行,其他列会自动复制。 示例代码(通用模板): import pandas as pd # 假设df是原始DataFrame,'column_name'是需要拆分的列,分隔符是逗号 df['column_name'] = df['column_name'].str.split(',') # 如果已经是列表,跳过这一步 df = df.explode('column_name') 如果需要重置索引,可以在explode后重置: df = df.explode('column_name').reset_index(drop=True) 注意:explode也可以同时拆分多个列,但要这些列在每一行的列表长度相同。例如: df = df.explode(['col1','col2']) 但是,如果多个列拆分的长度不同,则不能直接同时explode,需要分别处理或使用其他方法(如方法五)。 对于大数据量,如果explode性能不佳,可以考虑引用[2]中的方法二(使用numpy): 步骤如下: 1. 将需要拆分的列拆分成列表,并计算每行拆分后的长度(记录为rs) 2. 使用np.repeat重复其他列的值(重复次数为rs) 3. 使用np.concatenate获取拆分后该列的所有值 4. 构建新的DataFrame 示例(针对一列拆分): import numpy as np # 假设我们要拆分'var1'列,并且有'var2'列需要重复 # 将var1拆分成列表 df['var1'] = df['var1'].str.split(',') # 计算每行拆分后的长度 lens = df['var1'].apply(len) # 创建新DataFrame:重复其他列 new_df = pd.DataFrame({ 'var2': np.repeat(df['var2'], lens), 'var1': np.concatenate(df['var1']) }) # 如果还有其他列需要重复,也可以类似处理(注意:如果有多个列需要同时拆分,则这里要复杂些) 最后,我们给出一个完整的例子: 需:将下面数据中的'tags'列(逗号分隔)拆分成多行,其他列重复。 id name tags 1 Alice a,b,c 2 Bob d,e 代码: import pandas as pd data = { 'id': [1, 2], 'name': ['Alice', 'Bob'], 'tags': ['a,b,c', 'd,e'] } df = pd.DataFrame(data) # 拆分 df['tags'] = df['tags'].str.split(',') df = df.explode('tags').reset_index(drop=True) print(df) 输出: id name tags 1 Alice a 1 Alice b 1 Alice c 2 Bob d 2 Bob e 如果用户需要同时拆分多个列,且长度相同,比如有两个列都是逗号分隔,且每行拆分的元素个数相同: id name tags scores 1 Alice a,b,c 90,80,70 2 Bob d,e 95,85 注意:第二行拆分长度不同(第一行3个,第二行2个),则不能同时拆分。如果要拆分,则需要分别拆分,但这样会导致行数不一致,通常需要分别拆分然后合并,但这样会破坏结构。 因此,一般情况下,我们只拆分一个列,其他列作为重复。如果一定要拆分多个列,则要拆分后每列的长度相同。 例如,如果每行拆分长度都相同,则可以: df['tags'] = df['tags'].str.split(',') df['scores'] = df['scores'].str.split(',') df = df.explode(['tags','scores']) 这样,tags和scores会同时拆分成多行,并且一一对应。 综上所述,我们推荐使用explode方法,它简单高效。 注意:pandas的explode方法要pandas版本>=0.25.0,如果版本过低,可以使用引用[2]中的方法一(concat+Series)或者升级pandas。 因此,回答用户的问题: Python DataFrame将一行数据转换为多行数据的实现方法主要有: 1. 使用pandas的explode方法(推荐,简单直观) 2. 使用numpy进行高效处理(适用于大数据量或低版本pandas) 我们给出两种方法的代码示例。 方法一:使用explode(适用于单个列拆分) 步骤: - 将字符串列拆分成列表(使用split) - 调用explode方法 - 可选:重置索引 方法二:使用numpy(适用于单个列拆分,且需要高性能) 步骤: - 将字符串列拆分成列表 - 计算每行拆分后的长度 - 使用np.repeat重复其他列的值 - 使用np.concatenate连接拆分后的值 - 构建新的DataFrame 我们根据用户的需选择合适的方法。 </think> ### Python DataFrame一行转多行实现方法 在Python的Pandas库中,将一行数据转换为多行数据(行展开)主要有两种常见场景,以下是具体实现方法: #### 方法一:使用`explode()`函数(推荐) **适用场景**:单列数据包含分隔符或列表,需要按分隔符拆分成多行 ```python import pandas as pd # 原始数据(一行含逗号分隔值) df = pd.DataFrame({ '姓名': ['张三'], '产品': ['A,B,C'], # 需拆分的列 '销售额': [1500] }) # 转换步骤 df['产品'] = df['产品'].str.split(',') # 转换为列表 df = df.explode('产品') # 核心展开操作 print(df) ``` **输出**: ``` 姓名 产品 销售额 0 张三 A 1500 0 张三 B 1500 0 张三 C 1500 ``` **特点**: - 自动复制其他列数据 - 支持多列同时展开(如`df.explode(['列1','列2'])`) - 需Pandas 0.25+版本[^2][^3] #### 方法二:使用`split()`+`stack()`组合 **适用场景**:需要更精细控制拆分过程 ```python # 原始数据 df = pd.DataFrame({ 'ID': [1], 'Tags': ['Python,Data,Analysis'] }) # 转换步骤 split_df = ( df.set_index('ID')['Tags'] .str.split(',', expand=True) .stack() .reset_index(name='Tag') .drop('level_1', axis=1) ) print(split_df) ``` **输出**: ``` ID Tag 0 1 Python 1 1 Data 2 1 Analysis ``` #### 高阶场景:多列关联展开 当需要同时展开多列且保持值对应关系时(如产品与销售额一一对应): ```python # 原始数据(多列列表) df = pd.DataFrame({ '姓名': ['李四'], '产品': [['手机', '平板']], '销售额': [[5000, 3000]] }) # 同时展开多列 df = df.apply(pd.Series.explode) print(df) ``` **输出**: ``` 姓名 产品 销售额 0 李四 手机 5000 0 李四 平板 3000 ``` #### ⚠️ 注意事项 1. 数据类型需统一:确保拆分列是字符串或列表类型 2. 索引处理:展开后索引会重复,建议`reset_index(drop=True)` 3. 性能优化:大数据集优先用`np.repeat`(参考引用[2]方法二) 4. 空值处理:使用`df.dropna()`过滤空列表 > 关键要点:核心函数`explode()`可处理90%的行转多行,复杂场景结合`str.split()`和`stack()`实现精确控制[^1][^2][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值