访问存储在pandas dataframe中的数组

时间:2017-09-21 20:29:52

标签: python arrays pandas numpy

我有一个pandas数据帧,其中一列包含1-D 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]更清晰。

我的问题是:是否有更好/更清洁/更短的方式以我放入的格式访问数据?或者这只是我必须忍受的东西?

3 个答案:

答案 0 :(得分:2)

不同之处不在于数组是一个对象,而是您指定的查询可能返回多个对象(因此外部数组())。如果您确信查询只返回一个对象,那么您可以使用@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)

答案 1 :(得分:0)

您可以使用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

答案 2 :(得分:0)

使用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
棘手的词典
我对这个选项并不是很认真。我只是觉得很酷。正如评论中所提到的,有许多事情可能会出错。

dict(df.values)['x']

[1, 2, 3]

然而,稍作修改,我们可以提高稳健性。

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