python - Pandas:将宽数据框 reshape 为多索引长数据框

标签 python pandas

我有一个照片评分数据集,由许多个人评分者生成。
每个评分者都会收到几张要评分的图像,对于每张图像,评分者都会提供几个不同的评分以及描述。

例如,评分者可能会被要求对 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 。含义:

url1 | url2 | url3
-----|------|-----
  a  |   b  |  c

变成了

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 | 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 的方法工具,包括 meltwide_to_long ,但我不知道如何首先将照片网址转换为长格式,然后创建一个嵌套索引来排列数据,如我上面介绍的那样。我对 Pandas 很满意groupby和基本聚合,但这有点超出了我的技能水平。非常感谢任何帮助!

注意:我在这些虚拟数据中给出的字段并不是实际数据集中的确切名称,但它们完全遵循相同的命名约定。照片网址都是url1 , url2等,评级字段表示为 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']

最佳答案

您可以首先通过 str.contains 查找每个类别的列然后使用不为人知的pd.lreshape。最后聚合列 mean , var , count加入:

#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]
print df
     rater_id_count  rat2_mean  rat2_var  rat1_mean  rat1_var  \
url                                                             
a                 2        3.5       2.0        2.0       2.0   
b                 2        2.5       2.0        3.5       0.5   
c                 1        5.0       NaN        5.0       NaN   
d                 1        3.5       NaN        1.0       NaN   

              desc_join  
url                      
a    sunny day sunshine  
b        rainy day rain  
c             foggy day  
d                  snow  

关于python - Pandas:将宽数据框 reshape 为多索引长数据框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36451918/

相关文章:

python - MySQL/MariaDB 在数亿数据后插入缓慢

python - 我安装了一个 Python 程序,但找不到它的所有源代码

python - Python2.7 中的错误正好需要 2 个参数(给定 1 个)

Python 数据框 : Dropping duplicates base on certain conditions

python - 类型错误 : include and exclude must both be non-string sequences

python - 是否有一个 NumPy 函数来返回数组中某物的第一个索引?

python - 使用表单字段更新 Django 模型

python - Pandas 将数据框写入带有附加的 Parquet 格式

python - Groupby() 以逗号分隔的单词

python - Pandas 数据帧组 : sum one column, 从其他人那里获取第一个元素