【问题标题】:Creating a new column with value of another column, conditioned on multiple other columns shared across indices创建具有另一列值的新列,以跨索引共享的多个其他列为条件
【发布时间】:2019-12-18 17:39:44
【问题描述】:

我使用 pandas 中的数据集,该数据集包含大约 118k 对所玩游戏的观察结果,每个观察结果应该有两个条目。当我第一次遇到条目 A 时,我需要根据当前观察中的三个值找到另一个观察,并使用不同列的值创建一个新列。抱歉,如果这不能在所有设备上正确呈现...我不确定如何在 SO 上格式化 pandas 表,但我的数据看起来像这样:

   date | user_a_id | user_b_id | a_points | b_points | b_wins | a_result
0  12.1     20834     65168         65165      10568      5         W
1  12.1     20834     84163         65165      88452     21         W
2  12.2     20834     61806         65165      25998     19         L
3  12.1     84163     20834         88452      65165     33         L
4  12.3     96844     10196         22609      167005    52         W

每个玩家都有大量额外数据,但我们需要创建一个新列的值是b_wins。每一行都是一个游戏的故事,但a_result 是用户 A 的游戏结果。b_wins 是一个有用的数据,它告诉我们玩家在比赛中的经验,我相信这会具有很高的预测价值,因此不建议放弃它。

在本例中,第 1 行和第 3 行讲述了同一个游戏的故事。我需要df.iloc[3].at['b_wins'] 的值才能转到df.iloc[1] 处名为a_wins 的新列,反之亦然。得到的两个指标如下所示:

   date | user_a_id | user_b_id | a_points | b_points | b_wins | a_result | a_wins
1  12.1     20834     84163         65165      88452     21         W         33
3  12.1     84163     20834         88452      65165     33         L         21

关于数据的一些注意事项:

  • 并非每场比赛都有一对。这些数据是从网站上抓取的,非常混乱。可能只有一个观察结果,没关系。
  • 没有游戏ID,所以只能匹配日期和切换的用户ID号。
  • 有很多复赛。因此,虽然我可以匹配转换后的 ID 号,但我也无法按日期过滤它们
  • 到目前为止,我的大部分工作都是在 Colab Notebook 中完成的。我是第一次开始使用 python shell,没有骰子。

我尝试过的:

df['a_wins'] = df['user_a_id'].apply(lambda x: df.loc[df["user_b_id"] == x, "b_wins"].values)

似乎偶尔会起作用。我没有得到每一个价值,也没有得到复赛。要尝试按日期过滤,然后我尝试了:

for i in df['date']:
  grouped = df.groupby['date'].get_group(i)
  df['a_wins'] = grouped['user_a_id'].apply(lambda x: grouped.loc[grouped["user_b_id"] == x, "b_wins"].values)

也只能偶尔使用。两者都需要永远! :)

【问题讨论】:

    标签: python pandas dataframe filtering


    【解决方案1】:

    创建缺失的列:

    # initialise a_wins, b_result
    df['a_wins'] = None
    df['b_result'] = df['a_result'].replace({'W':'L','L':'W'})
    

    想法是交换内容,使较小的id 始终为a

    # which values to swap
    df['swap'] = df['user_a_id'] > df['user_b_id']
    

    使用相应的列名创建列表

    # works for the data you posted, might want to adjust.
    a_list = sorted([a for a in df.columns if 'a_' in a])
    b_list = sorted([b for b in df.columns if 'b_' in b])
    

    在满足切换条件的地方交换a/b内容:

    for a, b in zip(a_list, b_list):
        df.loc[df['swap'], a], df.loc[df['swap'], b] = df[df['swap']][b], df[df['swap']][a]
    

    输出:

    date    user_a_id   user_b_id   a_points    b_points    b_wins  a_result    swap    a_wins  b_result
    0   12.1    20834   65168   65165   10568   5   W   False   None    L
    1   12.1    20834   84163   65165   88452   21  W   False   None    L
    2   12.2    20834   61806   65165   25998   19  L   False   None    W
    3   12.1    20834   84163   65165   88452   None    W   True    33  L
    4   12.3    10196   96844   167005  22609   None    L   True    52  W
    

    编辑:

    现在可以通过按date, user_a_id, user_b_id 分组并填充None 值来复制条目:

    df = df.groupby(['date','user_b_id', 'user_a_id'])[df.columns].fillna(method='ffill').fillna(method='bfill')
    

    现在,您可以使用交换列恢复原始格式:

    for a, b in zip(a_list, b_list):
        df.loc[df['swap'], a], df.loc[df['swap'], b] = df[df['swap']][b], df[df['swap']][a]
    

    输出:

    date    user_a_id   user_b_id   a_points    b_points    b_wins  a_result    a_wins  b_result    swap
    0   12.1    20834   65168   65165   10568   5.0 W   33.0    L   False
    1   12.1    20834   84163   65165   88452   21.0    W   33.0    L   False
    2   12.2    20834   61806   65165   25998   19.0    L   33.0    W   False
    3   12.1    84163   20834   88452   65165   33.0    L   21.0    W   True
    4   12.3    96844   10196   22609   167005  52.0    W   NaN L   True
    

    【讨论】:

    • 经过大量探索后,我发现所有这些只是切换 a => b 和 b =>a 而不会在任何观察中创建任何新数据。有趣的解决方案,虽然(而且超级快)所以我赞成它,但它并没有解决我的问题。 b_wins 总是有一个值,即使我的数据框中没有匹配的游戏。
    • 我一定误解了你的问题。不过,感谢您的支持。我对其进行了编辑,使其交换 -> 填充缺失值 -> 交换回来。这在 100k 行数据帧中应该足够快。
    猜你喜欢
    • 2012-08-24
    • 1970-01-01
    • 1970-01-01
    • 2017-08-15
    • 2017-08-12
    • 1970-01-01
    • 2018-02-27
    • 2021-12-26
    • 2021-04-20
    相关资源
    最近更新 更多