在 pandas 中查找与数组匹配的列名

Posted

技术标签:

【中文标题】在 pandas 中查找与数组匹配的列名【英文标题】:Find column name in pandas that matches an array 【发布时间】:2017-12-31 23:17:23 【问题描述】:

我有一个大数据框 (5000 x 12039),我想获取与 numpy 数组匹配的列名。

例如,如果我有桌子

        m1lenhr m1lenmin    m1citywt    m1a12a  cm1age  cm1numb m1b1a   m1b1b   m1b12a  m1b12b  ... kind_attention_scale_10 kind_attention_scale_22 kind_attention_scale_21 kind_attention_scale_15 kind_attention_scale_18 kind_attention_scale_19 kind_attention_scale_25 kind_attention_scale_24 kind_attention_scale_27 kind_attention_scale_23
challengeID                                                                                 
1   0.130765    40.0    202.485367  1.893256    27.0    1.0 2.0 0.0 2.254198    2.289966    ... 0   0   0   0   0   0   0   0   0   0
2   0.000000    40.0    45.608219   1.000000    24.0    1.0 2.0 0.0 2.000000    3.000000    ... 0   0   0   0   0   0   0   0   0   0
3   0.000000    35.0    39.060299   2.000000    23.0    1.0 2.0 0.0 2.254198    2.289966    ... 0   0   0   0   0   0   0   0   0   0
4   0.000000    30.0    22.304855   1.893256    22.0    1.0 3.0 0.0 2.000000    3.000000    ... 0   0   0   0   0   0   0   0   0   0
5   0.000000    25.0    35.518272   1.893256    19.0    1.0 1.0 6.0 1.000000    3.000000    ... 0

我想这样做:

x = [40.0, 40.0, 35.0, 30.0, 25.0]
find_column(x)

find_column(x)返回m1lenmin

【问题讨论】:

【参考方案1】:

方法#1

这是一种利用 NumPy broadcasting 的矢量化方法 -

df.columns[(df.values == np.asarray(x)[:,None]).all(0)]

示例运行 -

In [367]: df
Out[367]: 
   0  1  2  3  4  5  6  7  8  9
0  7  1  2  6  2  1  7  2  0  6
1  5  4  3  3  2  1  1  1  5  5
2  7  7  2  2  5  4  6  6  5  7
3  0  5  4  1  5  7  8  2  2  4
4  7  1  0  4  5  4  3  2  8  6

In [368]: x = df.iloc[:,2].values.tolist()

In [369]: x
Out[369]: [2, 3, 2, 4, 0]

In [370]: df.columns[(df.values == np.asarray(x)[:,None]).all(0)]
Out[370]: Int64Index([2], dtype='int64')

方法 #2

另外,这里有另一个使用views 的概念-

def view1D(a, b): # a, b are arrays
    a = np.ascontiguousarray(a)
    b = np.ascontiguousarray(b)
    void_dt = np.dtype((np.void, a.dtype.itemsize * a.shape[1]))
    return a.view(void_dt).ravel(),  b.view(void_dt).ravel()

df1D_arr, x1D = view1D(df.values.T,np.asarray(x)[None])
out = np.flatnonzero(df1D_arr==x1D)

示例运行 -

In [442]: df
Out[442]: 
   0  1  2  3  4  5  6  7  8  9
0  7  1  2  6  2  1  7  2  0  6
1  5  4  3  3  2  1  1  1  5  5
2  7  7  2  2  5  4  6  6  5  7
3  0  5  4  1  5  7  8  2  2  4
4  7  1  0  4  5  4  3  2  8  6

In [443]: x = df.iloc[:,5].values.tolist()

In [444]: df1D_arr, x1D = view1D(df.values.T,np.asarray(x)[None])

In [445]: np.flatnonzero(df1D_arr==x1D)
Out[445]: array([5])

【讨论】:

是的,这个更优雅! :) @Divakar 你有任何关于 numpy 的教程博客可以向你学习吗? @MSS 哈哈,还没有。但是,这是一个很好的要求!【参考方案2】:

试试这个:

In [91]: x = np.array(x)

In [94]: df.apply(lambda col: col.eq(x).all())
Out[94]:
m1lenhr     False
m1lenmin     True
m1citywt    False
m1a12a      False
cm1age      False
cm1numb     False
m1b1a       False
m1b1b       False
m1b12a      False
m1b12b      False
dtype: bool

In [95]: df.columns[df.apply(lambda col: col.eq(x).all()).values]
Out[95]: Index(['m1lenmin'], dtype='object')

【讨论】:

【参考方案3】:

您可以使用axis 参数设置为0'index' 的方法eq(获取相等):

df = pd.DataFrame('A': [3, 4, 5, 6], 'B': [1, 2, 2, 2])

df.columns[df.eq([1, 2, 2, 2], axis=0).all(0)]

df.columns[df.eq([1, 2, 2, 2], axis='index').all('index')]

输出:

Index(['B'], dtype='object')

【讨论】:

以上是关于在 pandas 中查找与数组匹配的列名的主要内容,如果未能解决你的问题,请参考以下文章

如何将带有无效字符(重音)的 Pandas 数据框与数组匹配? [复制]

pandas的loc与iloc

如果行中有匹配项,则返回列名,查找多个匹配项[重复]

如果存在与数据中的某些条件匹配的另一行,则从pandas DataFrame中查找行

在 pandas Intervalindex 中查找匹配间隔

在 Pandas 数据框中高效、快速地查找和匹配唯一值