【问题标题】:How to find rows in a dataframe based on other rows and other dataframes如何根据其他行和其他数据框查找数据框中的行
【发布时间】:2019-06-26 04:03:12
【问题描述】:

从我问here 的问题中,我得到了一个类似于此的 JSON 响应:

(请注意:我下面的示例数据中的id 是数字字符串,但有些是字母数字)

data=↓**

{
  "state": "active",
  "team_size": 20,
  "teams": {
    "id": "12345679",
    "name": "Good Guys",
    "level": 10,
    "attacks": 4,
    "destruction_percentage": 22.6,
    "members": [
      {
        "id": "1",
        "name": "John",
        "level": 12
      },
      {
        "id": "2",
        "name": "Tom",
        "level": 11,
        "attacks": [
          {
            "attackerTag": "2",
            "defenderTag": "4",
            "damage": 64,
            "order": 7
          }
        ]
      }
    ]
  },
  "opponent": {
    "id": "987654321",
    "name": "Bad Guys",
    "level": 17,
    "attacks": 5,
    "damage": 20.95,
    "members": [
      {
        "id": "3",
        "name": "Betty",
        "level": 17,
        "attacks": [
          {
            "attacker_id": "3",
            "defender_id": "1",
            "damage": 70,
            "order": 1
          },
          {
            "attacker_id": "3",
            "defender_id": "7",
            "damage": 100,
            "order": 11
          }
        ],
        "opponentAttacks": 0,
        "some_useless_data": "Want to ignore, this doesn't show in every record"
      },
      {
        "id": "4",
        "name": "Fred",
        "level": 9,
        "attacks": [
          {
            "attacker_id": "4",
            "defender_id": "9",
            "damage": 70,
            "order": 4
          }
        ],
        "opponentAttacks": 0
      }
    ]
  }
}

我使用以下方式加载了这个:

df = json_normalize([data['team'], data['opponent']],
                     'members',
                     ['id', 'name'],
                     meta_prefix='team.',
                     errors='ignore')
print(df.iloc(1))
attacks              [{'damage': 70, 'order': 4, 'defender_id': '9'...
id                                                                   4
level                                                                9
name                                                              Fred
opponentAttacks                                                      0
some_useless_data                                                  NaN
team.name                                                     Bad Guys
team.id                                                      987654321
Name: 3, dtype: object

我有一个 3 部分的问题。

  1. 如何使用成员标签获得与上述类似的行?我试过了:

    member = df[df['id']=="1"].iloc[0]
    #Now this works, but am I correctly doing this?
    #It just feels weird is all.
    
  2. 如果只记录攻击而不记录防御,我将如何检索成员的防御(即使给出了defender_id)?我试过了:

    df.where(df['tag']==df['attacks'].str.get('defender_id'), df['attacks'], axis=0)
    #This is totally not working.. Where am I going wrong?
    
  3. 由于我正在从 API 检索新数据,因此我需要检查数据库中的旧数据以查看是否有任何新攻击。然后我可以循环浏览新的攻击,然后向用户显示攻击信息。

    老实说,我无法弄清楚这一点,我已经尝试过查看 this questionthis one 以及我觉得任何地方都接近我需要的东西,但仍然无法将我的大脑包裹在这个概念上。基本上我的逻辑如下:

    def get_new_attacks(old_data, new_data)
        '''params
             old_data: Dataframe loaded from JSON in database
             new_data: Dataframe loaded from JSON API response
                       hopefully having new attacks
           returns:
             iterator over the new attacks
        '''
    
        #calculate a dataframe with new attacks listed
        return df.iterrows()
    

我知道上面的函数除了我提供的文档之外几乎没有任何努力(基本上是为了显示我想要的输入/输出)但相信我,我一直在为这部分绞尽脑汁最多。我一直在研究merging 所有攻击,然后做reset_index(),由于攻击是一个列表,这只会引发一个错误。我上面链接的第二个问题中的map() 函数让我很难过。

【问题讨论】:

  • 现在已经一个小时了,我为模糊的标题道歉,刚刚编辑。我不知道那里发生了什么。
  • df1 是什么?是df.iloc[1]吗?
  • 应该是df。我的错,我一直在研究如何使用 pandas。我找到了答案,@a_guest 回答正确。
  • 是的,我也准备这么说:-)

标签: python pandas python-3.7


【解决方案1】:

按顺序参考您的问题(代码如下):

  1. 我看起来id 是数据的唯一索引,因此您可以使用df.set_index('id'),它允许您通过例如df.loc['1'] 按玩家ID 访问数据。
  2. 据我了解您的数据,每个attacks 中列出的所有字典都是自包含的,在某种意义上不需要相应的玩家ID(如attacker_iddefender_id 似乎就足够了识别数据)。因此,我建议不要处理包含列表的行,而是将这些数据换出到自己的数据框中,这样可以轻松访问。
  3. attacks 存储在其自己的数据框中后,您可以简单地比较索引以过滤掉旧数据。

这里有一些示例代码来说明各个点:

# Question 1.
df.set_index('id', inplace=True)
print(df.loc['1'])  # For example player id 1.

# Question 2 & 3.
attacks = pd.concat(map(
    lambda x: pd.DataFrame.from_dict(x).set_index('order'),  # Is 'order' the right index?
    df['attacks'].dropna()
))

# Question 2.
print(attacks[attacks['defender_id'] == '1'])  # For example defender_id 1.

# Question 3.
old_attacks = attacks.iloc[:2]  # For example.
new_attacks = attacks[~attacks.index.isin(old_attacks.index)]
print(new_attacks)

【讨论】:

  • 谢谢,我知道这些都是新手问题。我刚刚开始使用 pandas 并且无法理解它的细微差别。这几天做了很多研究,一直在看视频。感谢您的精彩回答!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-01
  • 1970-01-01
  • 2021-09-15
  • 2022-07-01
  • 2017-01-16
  • 2018-03-11
  • 2023-03-17
相关资源
最近更新 更多