【问题标题】:accessing arrays stored in pandas dataframe访问存储在 pandas 数据框中的数组
【发布时间】:2017-09-21 20:29:52
【问题描述】:

我有一个 pandas 数据框,其中一列包含一维 numpy 数组,另一列包含标量数据,例如:

df =
    A   B
0   x   [0, 1, 2]
1   y   [0, 1, 2]
2   z   [0, 1, 2]

我想为 A=='x' 所在的行获取 B 所以我尝试了 df[df.A == 'x'].B.values 这给了我输出:

array([array([0, 1, 2])], dtype=object)

输出周围有一个额外的array([])。我知道 Pandas 将它视为一个对象而不仅仅是数据,我有一种方法可以使用 df[df.A == 'x'].B.values[0] 来访问数组。对于标量数据,我可以只使用语法df[df.A == 'x'].B,它比我必须使用的df[df.A == 'x'].B.values[0] 干净得多。

我的问题是:有没有更好/更干净/更短的方法来访问我输入的格式的数据?还是这只是我必须忍受的事情?

【问题讨论】:

  • 或者你可以使用...df[df.A==10].B.item()

标签: python arrays pandas numpy


【解决方案1】:

不同之处不在于数组是一个对象,而是您指定的查询可以返回多个对象(因此是外部数组())。如果您确信查询将只返回一个对象,那么您可以使用@Wen 的解决方案来使用.item()

In [1]: import pandas as pd

In [2]: df = pd.DataFrame([
   ...: dict(A='x', B=[0,1,2]),
   ...: dict(A='y', B=[0,1,2]),
   ...: dict(A='z', B=[0,1,2]),
   ...: ])

In [3]: df[df.A == 'x'].B.item()
Out[3]: [0, 1, 2]

但是根据查询的类型,您至少应该考虑检查结果以确保:

In [4]: df = pd.DataFrame([
   ...: dict(A='x', B=[0,1,2]),
   ...: dict(A='y', B=[0,1,2]),
   ...: dict(A='z', B=[0,1,2]),
   ...: dict(A='x', B=[3,3,3]),
   ...: ])

In [5]: df[df.A == 'x'].B.item()
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-8-e0ad528e719e> in <module>()
----> 1 df[df.A == 'x'].B.item()

   ...

ValueError: can only convert an array of size 1 to a Python scalar

In [6]: df[df.A == 'x'].B.values
Out[6]: array([[0, 1, 2], [3, 3, 3]], dtype=object)

【讨论】:

    【解决方案2】:

    您可以使用squeeze 方法。如果应用过滤器后的结果仅包含一行,它将返回该行的内容,因为它会将其转换为低一维。

    In[103]: df = pd.DataFrame([['x', [1, 2, 3]], ['y', [1, 2, 3]], ['y', [1, 2, 3]]], index=[0, 1, 2], columns=['A', 'B'])
    In[104]: df
    Out[104]: 
       A          B
    0  x  [1, 2, 3]
    1  y  [1, 2, 3]
    2  y  [1, 2, 3]
    
    In[105]: df[df.A == 'x'].B.squeeze()
    Out[105]: [1, 2, 3]
    
    In[106]: df[df.A == 'y'].B.squeeze()
    Out[106]: 
    1    [1, 2, 3]
    2    [1, 2, 3]
    Name: B, dtype: object
    

    【讨论】:

      【解决方案3】:

      使用loc 时,您将获得不同的对象,具体取决于您传递的索引器。在您的示例中:

      df.loc[df.A == 'x', 'B']
      

      您传递了df.A == 'x',它返回一个布尔值pd.Series。由于这是一个类似于输入的数组,因此可以保证获得扩展索引维度的输出。

      现在,因为第二个索引器是标量 'B',所以您不会扩展列维度。因此,输出的是一个pd.Series 对象,其索引由布尔系列df.A == 'x'True 且名称为'B' 的所有索引值组成。

      0    [1, 2, 3]
      Name: B, dtype: object
      

      简而言之这与'B'列中的数组无关


      选项 1
      df.A == 'x'获取标量结果

      df.loc[df.A.eq('x').idxmax(), 'B']
      
      [1, 2, 3]
      

      选项 2
      设置索引

      df.set_index('A').B.loc['x']
      
      [1, 2, 3]
      

      选项 3
      棘手的字典
      我对这个选项并不认真。我只是觉得这很酷。正如 cmets 中提到的,它有很多可能出错的地方。

      dict(df.values)['x']
      
      [1, 2, 3]
      

      但是,稍作修改,我们可以提高鲁棒性。

      dict(df[['A', 'B']].values)['x']
      

      【讨论】:

      • 我喜欢那个棘手的 dict,但它对 DF 的布局非常敏感。如果你做了dict(df[['A', 'B']].values)['x'],它会更通用一点。如果需要多次执行此操作,选项 2 可能是总体上最好的选项。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-03
      • 2020-12-03
      • 2021-11-15
      • 1970-01-01
      • 1970-01-01
      • 2015-04-10
      • 1970-01-01
      相关资源
      最近更新 更多