【问题标题】:Selecting single values from pandas dataframe using lists使用列表从熊猫数据框中选择单个值
【发布时间】:2018-03-30 16:26:00
【问题描述】:
import numpy as np
import pandas as pd

ind = [0, 1, 2]
cols = ['A','B','C']
df = pd.DataFrame(np.arange(9).reshape((3,3)),columns=cols)

假设你有一个熊猫数据框df,看起来像:

    A  B  C
 0  0  1  2
 1  3  4  5
 2  6  7  8    

如果您想从cols 中特定索引ind 的每一列中捕获单个元素,则输出应该看起来像一个系列:

 A  0
 B  4
 C  8

到目前为止我尝试过的是:

 df.loc[ind,cols]

它给出了不想要的输出:

   A  B  C
0  0  1  2
1  3  4  5
2  6  7  8

有什么建议吗?

上下文: 下一步是将一个数据帧的df.idxmax() 调用的输出映射到另一个具有相同列名和索引的数据帧,但如果我知道如何进行上述转换,我可能会弄清楚这一点。

【问题讨论】:

  • 你能澄清一下这个问题吗?您需要返回的值是否始终与索引和列的顺序相同? (即您总是想要对角线值)还是会在此 df.loc[ind,cols] 中更改值的顺序?
  • 你为 ind 和 cols 传递了什么给你的结果?显然传递ind 和cols 只是传递您上面定义的所有索引和列,那么您为什么会期望一个奇异值呢?

标签: python pandas dataframe indexing


【解决方案1】:

如果你喜欢使用 .loc,还有另一种使用 mutiIndex 的方法

df1=df.reset_index().melt('index').set_index(['index','variable'])
df1.loc[list(zip(df.index,df.columns))]
Out[118]: 
                value
index variable       
0     A             0
1     B             4
2     C             8

【讨论】:

    【解决方案2】:

    这是一个带有 NumPy 的 advanced-indexing 的矢量化元素,用于在每列给定行索引 ind 的情况下每列选择一个元素 -

    pd.Series(df.values[ind, np.arange(len(ind))], df.columns)
    

    示例运行 -

    In [107]: ind = [0, 2, 1] # different one than sample for variety
         ...: cols = ['A','B','C']
         ...: df = pd.DataFrame(np.arange(9).reshape((3,3)),columns=cols)
         ...: 
    
    In [109]: df
    Out[109]: 
       A  B  C
    0  0  1  2
    1  3  4  5
    2  6  7  8
    
    In [110]: pd.Series(df.values[ind, np.arange(len(ind))], df.columns)
    Out[110]: 
    A    0
    B    7
    C    5
    dtype: int64
    

    运行时测试

    让我们将提议的方法与@MaxU 的解决方案中提议的 pandas 内置矢量化 lookup 方法进行比较,既然我们看到了矢量化方法有多好,让我们有更多的列 -

    In [111]: ncols = 10000
         ...: df = pd.DataFrame(np.random.randint(0,9,(100,ncols)))
         ...: ind = np.random.randint(0,100,(ncols)).tolist()
         ...: 
    
    # @MaxU's solution
    In [112]: %timeit pd.Series(df.lookup(ind, df.columns), index=df.columns)
    1000 loops, best of 3: 718 µs per loop
    
    # Proposed in this post    
    In [113]: %timeit pd.Series(df.values[ind, np.arange(len(ind))], df.columns)
    1000 loops, best of 3: 410 µs per loop
    
    In [114]: ncols = 100000
         ...: df = pd.DataFrame(np.random.randint(0,9,(100,ncols)))
         ...: ind = np.random.randint(0,100,(ncols)).tolist()
         ...: 
    
    # @MaxU's solution
    In [115]: %timeit pd.Series(df.lookup(ind, df.columns), index=df.columns)
    100 loops, best of 3: 8.83 ms per loop
    
    # Proposed in this post
    In [116]: %timeit pd.Series(df.values[ind, np.arange(len(ind))], df.columns)
    100 loops, best of 3: 5.76 ms per loop
    

    【讨论】:

      【解决方案3】:

      您可以压缩要为其检索值的列和索引值,然后从中创建一个系列:

      pd.Series([df.loc[id_, col] for id_, col in zip(ind, cols)], df.columns)
      A    0
      B    4
      C    8
      

      或者如果你总是只需要对角线值:

      pd.Series(np.diag(df), df.columns)
      

      会快很多

      【讨论】:

        【解决方案4】:

        你可以使用DataFrame.lookup():

        In [6]: pd.Series(df.lookup(df.index, df.columns), index=df.columns)
        Out[6]:
        A    0
        B    4
        C    8
        dtype: int32
        

        或:

        In [14]: pd.Series(df.lookup(ind, cols), index=df.columns)
        Out[14]:
        A    0
        B    4
        C    8
        dtype: int32
        

        解释:

        In [12]: df.lookup(df.index, df.columns)
        Out[12]: array([0, 4, 8])
        

        【讨论】:

        • 呃,不就是df.lookup(ind, cols)吗?
        • @juanpa.arrivillaga,很遗憾没有 - 不会有索引值...
        • 这绝对比列表理解更可取
        • 好吧,我的意思是你仍然必须将它包装在 pd.Series 中,但我的意思是不要使用 df.index 和 df.columns,因为我认为 OP希望那些是任意的,即ind = [0, 1, 1]
        • @juanpa.arrivillaga,啊,我误会了你。当然我们可以使用:df.lookup(ind, cols) 如你所说
        【解决方案5】:

        应该有更直接的方法但是这是我能想到的,

        val = [df.iloc[i,i] for i in df.index]
        pd.Series(val, index = df.columns)
        
        A    0
        B    4
        C    8
        dtype: int64
        

        【讨论】:

          猜你喜欢
          • 2020-01-12
          • 1970-01-01
          • 2018-08-05
          • 2020-09-21
          • 1970-01-01
          • 1970-01-01
          • 2015-07-30
          • 1970-01-01
          相关资源
          最近更新 更多