熊猫:将宽数据框重塑为多索引长格式

2024-06-06 11:27:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个照片评分数据集,由许多个人评分员生成。
每个评分者都有几个要评分的图像,对于每个图像,评分者提供几个不同的评分,外加一个描述。在

所以,举例来说,一个评分员可能会被要求给3张不同的照片打分,并在0-5分的范围内对每张照片的快乐、悲伤和有趣程度进行单独评分。此外,评分员被要求提供每张照片的简短文字描述。在

同一张照片可以由多个评分员评分,但并非所有照片都由相同数量的评分员评分。在

目前我的数据是这样的(每个url代表一张照片):

rater_id | url1 | url2 | url3 | rating_1(1) | rating_2(1) | rating_1(2) | rating_2(2)   | rating_1(3) | rating_2(3) | description(1) | description(2) | description(3)
     001 |   a  |   b  |   c  |     3.0     |     2.5     |     4.0     |     1.5       |     5.0     |     5.0     |  sunny day     |  rainy day     |  foggy day
     002 |   a  |   b  |   d  |     1.0     |     4.5     |     3.0     |     3.5       |     1.0     |     3.5     |  sunshine      |  rain          |  snow

我正在努力实现一些转变。
首先,我想更改数据帧,使其按照片url建立索引-所有url字段(url1、url2等)合并为一个长列url。含义:

^{pr2}$

变成

url
---
 a
 b
 c

在每个url索引中,rater_id都有一个嵌套索引,该索引包含该评级者对给定照片的评级和描述。
例如:

                | rating_1 | rating_2 | description
url | rater_id
 a  |      001  |    3.0   |   2.5    |  sunny day
    |      002  |    1.0   |   4.5    |  sunshine
----|-----------|----------|----------|------------
 b  |      001  |    4.0   |   1.5    |  rainy day
    |      002  |    4.5   |   3.0    |  rain
----|-----------|----------|----------|------------
 c  |      001  |    5.0   |   5.0    |  foggy day
----|-----------|----------|----------|------------
 d  |      002  |    1.0   |   3.5    |  snow

最后,我要汇总每个照片url的评级和描述: -数值评分的均值和方差 -所有描述的制表符分隔字符串 -为每张照片评分的评分员人数

例如:

url | rating_1_avg | rating_1_var | rating_2_avg | rating_2_var | all_descriptions      | total_ratings 
 a  |     2.0      |     2.0      |     3.0      |     2.0      | sunny day    sunshine |      2
----|--------------|--------------|--------------|--------------|-----------------------|--------------
 b  |     4.25     |     0.125    |     2.25     |     1.125    | rainy day    rain     |      2
----|--------------|--------------|--------------|--------------|-----------------------|--------------
 c  |     5.0      |     NA       |     5.0      |     NA       | foggy day             |      1
----|--------------|--------------|--------------|--------------|-----------------------|--------------
 d  |     1.0      |     NA       |     3.5      |     NA       | snow                  |      1

我尝试过很多使用Pandas reshaping工具的方法,包括melt和{},但是我不知道如何首先将照片URL转换为长格式,然后创建一个嵌套索引来安排我上面介绍的数据。我对Pandasgroupby和基本聚合非常满意,但这有点超出了我的技能水平。非常感谢任何帮助!在

注意:我在这些虚拟数据中给出的字段并不是实际数据集中的确切名称,但它们完全遵循相同的命名约定。照片URL都是url1url2,等等,评级字段表示为rating_<rating_category_number>(<url_number>),例如rating_1(2)。描述字段表示为description(<url_number>),例如description(2)。在

下面是构建初始数据集的Python代码:

df = pd.DataFrame({'id': {0: '001', 1: '002'},
                   'url1': {0: 'a', 1: 'a'},
                   'url2': {0: 'b', 1: 'b'},
                   'url3': {0: 'c', 1: 'd'}})

df['rating_1(1)'] = [3.0, 1]
df['rating_2(1)'] = [2.5, 4.5]
df['rating_1(2)'] = [4.0, 3]
df['rating_2(2)'] = [1.5, 3.5]
df['rating_1(3)'] = [5.0, 1]
df['rating_2(3)'] = [5.0, 3.5]
df['description(1)'] = ['sunny day','sunshine']
df['description(2)'] = ['rainy day','rain']
df['description(3)'] = ['foggy day','snow']

Tags: 数据idurldfdescription评分照片rating
2条回答

您可以首先通过^{}找到每个类别的列,然后使用不知名的pd.lreshape。按^{}^{}^{}join进行的最后聚合列:

#select columns with each category
rat1 = df.columns[df.columns.str.contains(r'rating_1')].tolist()
print rat1
['rating_1(1)', 'rating_1(2)', 'rating_1(3)']

rat2 = df.columns[df.columns.str.contains(r'rating_2')].tolist()
url = df.columns[df.columns.str.contains(r'url')].tolist()
desc = df.columns[df.columns.str.contains(r'description')].tolist()

df =  pd.lreshape(df, {'rat1': rat1, 'rat2': rat2,'url': url,'desc': desc})
print df
  rater_id url  rat2  rat1       desc
0    '001'   a   2.5   3.0  sunny day
1    '002'   a   4.5   1.0   sunshine
2    '001'   b   1.5   4.0  rainy day
3    '002'   b   3.5   3.0       rain
4    '001'   c   5.0   5.0  foggy day
5    '002'   d   3.5   1.0       snow

#aggregate
df = df.groupby(['url']).agg({'rat1':['mean', 'var'],
                              'rat2':['mean', 'var'], 
                              'desc': ' '.join, 
                              'rater_id': 'count'})

#reset multiindex in columns
df.columns = ['_'.join(col) for col in df.columns.values]
^{pr2}$

我会做如下的事情

ids_url1 = ['id', 'rating_1(1)', 'rating_2(1)', 'rating_3(1)', 'description(1)']
ids_url2 = ['id', 'rating_1(2)', 'rating_2(2)', 'rating_3(2)', 'description(2)']
ids_url3 = ['id', 'rating_1(3)', 'rating_2(3)', 'rating_3(3)', 'description(3)']

df1 = pd.melt(df, id_vars=ids_url1, value_vars=['url1'])
df2 = pd.melt(df, id_vars=ids_url2, value_vars=['url2'])
df3 = pd.melt(df, id_vars=ids_url3, value_vars=['url3'])
df1.drop(axis=1, labels='variable', inplace=True)
df1.set_index(['value', 'id'], inplace=True)
df1.columns = ["rating_1", "rating_2", "rating_3", "description"]
df2.drop(axis=1, labels='variable', inplace=True)
df2.set_index(['value', 'id'], inplace=True)
df2.columns = ["rating_1", "rating_2", "rating_3", "description"]
df3.drop(axis=1, labels='variable', inplace=True)
df3.set_index(['value', 'id'], inplace=True)
df3.columns = ["rating_1", "rating_2", "rating_3", "description"]

dfn = pd.concat([df1,df2,df3], axis=0)

然后您可以根据需要执行groupby并将结果串联起来

^{pr2}$

相关问题 更多 >