微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

python – 使用Pandas的每个单独行(一对多)的多个结果

如果我有一个DataFrame,其中每一行都是一个人,每一列都是单独的属性,我如何获得一个新的DataFrame,将每个人映射到多个结果?

我已经尝试使用DataFrame.apply()这看起来最直观 – 但它给出了例外情况,如下例所示.添加broadcast = False或reduce = False没有帮助.

下面是一个简单的例子,显然,但要考虑每行映射到多行的任何情况.处理这个问题的最佳方法是什么?实际上,每行可以映射到不同数量的结果.这基本上是计算一对多的关系.

示例:我有一个DataFrame数据集,其中包含以下结构,我希望每个人都能获得即将到来的三个生日(我知道这很简单的例子).所以,来自:

+---+-------+------------+
|   | name  | birthdate  |
+---+-------+------------+
| 1 | John  | 1990-01-01 |
| 2 | Jane  | 1957-04-03 |
| 3 | Max   | 1987-02-03 |
| 4 | David | 1964-02-12 |
+---+-------+------------+

类似于:

+-------+------------+
| name  | birthday   |
+-------+------------+
| John  | 2016-01-01 |
| John  | 2017-01-01 |
| John  | 2018-01-01 |
| Jane  | 2016-04-03 |
| Jane  | 2017-04-03 |
| Jane  | 2018-04-03 |
| Max   | 2016-02-03 |
| Max   | 2017-02-03 |
| Max   | 2018-02-03 |
| David | 2016-02-12 |
| David | 2017-02-12 |
| David | 2018-02-12 |
+-------+------------+

直觉上,我会尝试这样的事情:

def get_birthdays(person):
    birthdays = []
    for year in range(2016, 2019):
        birthdays.append({
            'name': person.name,
            'birthday': person.birthdate.replace(year=year)
        })

    return pd.DataFrame(birthdays)

# with data as my original DataFrame
data.apply(get_birthdays, axis=1)

但是,这提出了:

ValueError: Could not broadcast input array from shape (3,2) into shape (3)

During handling of the above exception, another exception occurred:

[...]

ValueError: cannot copy sequence with size 2 to array axis with dimension 3

解决方法:

groupby版本的apply支持DataFrame作为您想要的方式的返回值:

import pandas as pd
from datetime import datetime

df = pd.DataFrame({
    'name': ['John', 'Jane', 'Max', 'David'],
    'birthdate': [datetime(1990,1,1), datetime(1957,4,3), datetime(1987,2,3), datetime(1964,2,12)],
})

def get_birthdays(df_x):
    d = {'name': [], 'birthday': []}
    name = df_x.iloc[0]['name']
    original = df_x.iloc[0]['birthdate']
    for year in range(2016, 2019):
        d['name'].append(name)
        d['birthday'].append(original.replace(year=year))
    return pd.DataFrame(d)

print df.groupby('name', group_keys=False).apply(get_birthdays).reset_index(drop=True)

输出

     birthday   name
0  2016-02-12  David
1  2017-02-12  David
2  2018-02-12  David
3  2016-04-03   Jane
4  2017-04-03   Jane
5  2018-04-03   Jane
6  2016-01-01   John
7  2017-01-01   John
8  2018-01-01   John
9  2016-02-03    Max
10 2017-02-03    Max
11 2018-02-03    Max

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐