使用重复索引值的pandas数据帧进行透视

8
我有一个数据框,其中每个用户在我的网站上加入并进行购买的行。
+---+-----+--------------------+---------+--------+-----+
|   | uid |        msg         |  _time  | gender | age |
+---+-----+--------------------+---------+--------+-----+
| 0 |   1 | confirmed_settings | 1/29/15 | M      |  37 |
| 1 |   1 | sale               | 4/13/15 | M      |  37 |
| 2 |   3 | confirmed_settings | 4/19/15 | M      |  35 |
| 3 |   4 | confirmed_settings | 2/21/15 | M      |  21 |
| 4 |   5 | confirmed_settings | 3/28/15 | M      |  18 |
| 5 |   4 | sale               | 3/15/15 | M      |  21 |
+---+-----+--------------------+---------+--------+-----+

我希望更改数据框,使每个uid的行都是唯一的,并且有名为saleconfirmed_settings的列,其中包含操作的时间戳。请注意,不是每个用户都有sale,但每个用户都有confirmed_settings。如下所示:

+---+-----+--------------------+---------+---------+--------+-----+
|   | uid | confirmed_settings |  sale   |  _time  | gender | age |
+---+-----+--------------------+---------+---------+--------+-----+
| 0 |   1 | 1/29/15            | 4/13/15 | 1/29/15 | M      |  37 |
| 1 |   3 | 4/19/15            | null    | 4/19/15 | M      |  35 |
| 2 |   4 | 2/21/15            | 3/15/15 | 2/21/15 | M      |  21 |
| 3 |   5 | 3/28/15            | null    | 3/28/15 | M      |  18 |
+---+-----+--------------------+---------+---------+--------+-----+

为了实现这个目标,我正在尝试:
df1 = df.pivot(index='uid', columns='msg', values='_time').reset_index()
df1 = df1.merge(df[['uid', 'gender', 'age']].drop_duplicates(), on='uid')

但是我遇到了这个错误:ValueError:索引包含重复条目,无法重新塑造

当我的数据框具有重复的索引值时,如何进行数据透视以转换数据框?


编辑: df1 = df.pivot_table(index='uid', columns='msg', values='_time').reset_index()

出现了这个错误 DataError:没有可聚合的数字类型,但我甚至不确定这是否是正确的路径。


2
这个帖子中有一个答案,其中有人使用了pivot_table()而不是pivot,并解决了相同的错误,值得一试吗? - Benjamin Rowell
@Benjamin,我看了那篇帖子并尝试过,但是收到了这个错误 -“DataError:No numeric types to aggregate”并决定不再继续该路径,因为我更不理解那个错误。你有什么想法? - metersk
1
再试一次,但这次先运行以下代码将你的 'uid' 列强制转换为数值类型:df['uid'] = df['uid'].astype(int) - Benjamin Rowell
@benjamin 仍然收到相同的错误。 - metersk
1
抱歉,目前这是我所知道的最好答案了。希望有人能为您解答。 - Benjamin Rowell
3个回答

7
我怀疑确实存在重复的uid-msg条目/键(例如,uid 2在msg下有2个confirmed_settings条目),这一点你在fixxxer答案的评论中已经提到了。如果确实存在重复的话,您不能使用pivot,因为您无法告诉它如何处理聚合过程中遇到的不同值(计数?最大值?平均值?总和?)。请注意,Index错误是指结果透视表df1的索引错误,而不是原始DataFrame df的错误。 pivot_table使您可以使用aggfunc参数进行操作。您觉得以下内容是否可行?
df1 = df.pivot_table(index = 'uid', columns = 'msg', values = '_time', aggfunc = len)

这将帮助您找出哪些用户消息记录具有重复条目(任何超过1个的条目),在清理它们之后,您可以在 df 上使用 pivot 成功地旋转 _time


在我的情况下,我有一个时间序列索引的数据框。通过使用这个透视表,我发现(回想起来很明显)在11月份的“退回”中,有两个具有相同时间戳、相同“columns”(这里是'hub')但不同“values”的小时。在这种情况下,我使用了df = df[~df.duplicated(subset = ['Date', 'hub'], keep='first')]来丢弃第二个小时。 - GrayOnGray

4

x 是您输入的数据框:

    uid               msg   _time   gender  age
0   1   confirmed_settings  1/29/15 M       37
1   1   sale                4/13/15 M       37
2   3   confirmed_settings  4/19/15 M       35
3   4   confirmed_settings  2/21/15 M       21
4   5   confirmed_settings  3/28/15 M       18
5   4   sale                3/15/15 M       21

y = x.pivot(index='uid', columns='msg', values='_time')
x.join(y).drop('msg', axis=1)

给你:
    uid _time   gender  age     confirmed_settings  sale
0   1   1/29/15     M   37                    NaN   NaN
1   1   4/13/15     M   37                1/29/15   4/13/15
2   3   4/19/15     M   35                    NaN   NaN
3   4   2/21/15     M   21                4/19/15   NaN
4   5   3/28/15     M   18                2/21/15   3/15/15
5   4   3/15/15     M   21                3/28/15   NaN

1
仍然在执行以下代码时出现错误 ValueError: Index contains duplicate entries, cannot reshapey = x.pivot(index='uid', columns='msg', values='_time') - metersk
我使用的是Pandas 0.16版本。你用的是哪个版本? - fixxxer
检查另一个答案是否有效?还是升级到0.16? - fixxxer
2
好的 - 我升级到了16.0,但它并没有解决问题,不过我想我找到了原因。我的数据集比例子要大得多,可能存在一些数据错误,其中一个用户有两个销售或两个确认设置。我会尝试更好地清理数据,然后你的解决方案应该可以奏效。 - metersk
让我们在聊天中继续这个讨论。点击此处进入聊天室 - fixxxer
显示剩余2条评论

3
你可以使用groupby按常见因素进行聚合,取时间的最大值以获取最近的日期,然后取消堆叠msg以便并排查看confirmed_settings和sale:
df.groupby(['uid', 'msg', 'gender', 'age']).time.max().unstack('msg')

msg            confirmed_settings     sale
uid gender age                            
1   M      37             1/29/15  4/13/15
3   M      35             4/19/15      NaN
4   M      21             2/21/15  3/15/15
5   M      18             3/28/15      NaN

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接