以索引之间共享的其他多个列为条件,创建一个具有另一列值的新列

时间:2019-12-17 05:44:12

标签: python pandas dataframe filtering

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

   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']的值才能在a_wins转到名为df.iloc[1]的新列,反之亦然。这样得出的两个指数将如下所示:

   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笔记本中进行。我是第一次开始使用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)

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

1 个答案:

答案 0 :(得分: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')

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

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