我在pandas数据框中有3,100个列。 column_names的示例是
[price_of_apple_2006_01,price_of_apple_2006_02, price_of_apple_2006_03,price_of_apple_2007_01, price_of_apple_2007_02,price_of_apple_2008_01, price_of_apple_2008_02,price_of_apple_2008_03, price_of_apple_2008_04,....,price_of_orange_2006_01, price_of_orange_2006_02,price_of_orange_2006_03, price_of_orange_2006_04 ...... price_of_iphone(2006年至2015年 每月),price_of_samsung(2006年至2015年每月), price_of_mango(2006年至2015年每月).....]
我想自动组合
等列[price_of_apple_2006_01,price_of_apple_2006_02, price_of_apple_2006_03] price_of_apple_2007_01, price_of_apple_2007_02,price_of_apple_2008_01, price_of_apple_2008_02,price_of_apple_2008_03, price_of_apple_2008_04, price_of_orange_2006_01,price_of_orange_2006_02,price_of_orange_2006_03, price_of_orange_2006_04,price_of_orange_2006_05,price_of_orange_2006_06 ......
并将它们转换为
price_of_apple_2006,price_of_apple_2007,price_of_apple_2008, price_of_orange_2006 .....
取平均值(即price_of_apple_2008有5个月,2006年有2个月,2007年有3个月等等(此处没有图案))
要做到这一点,我应该能够做3个步骤:
1)查找相似的列名并将它们分组到一个名称中 2)跟踪每组中有多少相似的列 3)取平均值
次要的:
另外,对于少数类型的列有12个月,所以我想将它们转换为季度并分析为此我需要2个步骤 1)我应该能够编写代码来查找12次列名(price_of_orange_2006_01,price_of_orange_2006_02,price_of_orange_2006_03 ....)
2)然后我应该能够平均它们并转换为按季度(price_of_orange_2006_Q1,price_of_orange_2006_Q2,price_of_orange_2006_Q3)
有人可以帮我解决这个问题,手动执行3,100列会花费我很多时间
答案 0 :(得分:1)
您可以将函数传递给groupby
方法,该方法对列名称起作用,如:
grouped = df.groupby(lambda col: col[:-3], axis=1)
average_prices = grouped.mean()
n_months = grouped.size()
按列传递axis=1
组。我不确定我指定的功能是否正是您想要的,但是从您展示的示例中,按照名称和年份对组名进行分组,假设名称以_01
表示月份的结尾。对于第二部分,您可以使用n_months
通过执行以下操作来确定哪些名称 - 年份组合有12个月:
with_full_year = n_months[n_months == 12].index
然后,您可以为原始数据框生成所有列的列表:
cols = [{}_{:0>2d}.format(name_year, month) for name_year in with_full_year
for month in range(1, 13)]
然后按季度编写更复杂的分组功能:
def groupby_quarter(col):
name, year, month = col.split('_')[-3:]
quarter = (int(month) - 1) / 3 + 1
return '{}_{}_Q{}'.format(name, year, quarter)
quarterly_means = df[cols].groupby(groupby_quarter, axis=1).mean()
编辑: 我不知道如何在不知道所有列的情况下从每列中提取月,年和水果,但这不应该很难。您可以从将列转换为系列开始,然后使用字符串方法:
cols = df.columns.to_series()
years = cols.str.extract('.*(\d{4}).*')
months = cols.str.extract('.*_(\d{2})(?!\d).*')
这使用正则表达式查找4位数字,然后使用2位数字后跟不是另一位数字。从示例中可以看出,您还可以按如下方式提取产品名称:
product = cols.str.replace('price_of', '').str.replace(.str.extract('_([a-z]*)_.*')
这假设'price_of'是除产品名称之外的列名称中唯一的小写非数字部分,并且产品名称在任一侧都有下划线。获取产品的另一种方法是初始化一个与列相同长度的数组,然后通过循环遍历产品来填充它(可能没有那么多):
products= np.empty(len(cols), dtype=str)
for product in ['apple', 'orange', 'samsung']:
products[col.str.contains(product)] = product
正如Paul H
建议的那样,此时最好创建一个多索引:
df.columns = pd.MultiIndex.from_arrays([product, year, month])