我经常尝试决定如何将numpy
数组与pandas
数据框中的多个但不是所有列相关联。
所以我想问一下,获取与数据框中的几个但不是所有列关联的值数组的最有效方法是什么?
示例
df = pd.DataFrame(np.arange(10).reshape(-1, 5), columns=list('ABCDE'))
print(df)
A B C D E
0 0 1 2 3 4
1 5 6 7 8 9
什么是最快的获取方式
df[['B', 'D']].values
array([[1, 3],
[6, 8]])
答案 0 :(得分:2)
我想到了这些方法......我更欢迎在分析中加入
<强> 结论 强>
对于少量列,似乎找到列位置和使用整数切片非常有效。但是对于大型数组和大量列,as_matrix
非常好(正如预期的那样)。
from timeit import timeit
import pandas as pd
import numpy as np
from string import ascii_uppercase as up
def slc_df_2val(df, cols):
return df[cols].values
def as_matrix(df, cols):
return df.as_matrix(cols)
def hstack_per_col(df, cols):
return np.hstack([df[c].values[:, None] for c in cols])
def stack_per_col_T(df, cols):
return np.stack([df[c].values for c in cols]).reshape(-1, len(cols))
def get_loc_slc_array(df, cols):
a = [df.columns.get_loc(c) for c in cols]
return df.values[:, a]
然后我进行以下测试
mcol = pd.MultiIndex.from_product([list(up[:10]), list(up[-10:])])
sizes = pd.MultiIndex.from_product(
[[10, 100, 1000, 10000], [1, 5, 10, 20, 30, 40]],
names=['n', 'm'])
methods = pd.Index(
'slc_df_2val as_matrix hstack_per_col stack_per_col_T get_loc_slc_array'.split(),
name='method')
results = pd.DataFrame(index=sizes, columns=methods)
np.random.seed([3,1415])
for n in sizes.levels[0]:
df = pd.DataFrame(np.arange(n * 100).reshape(-1, 100), columns=mcol)
for m in sizes.levels[1]:
cols = np.random.choice(mcol, m, replace=False)
for f in methods:
stmt = '{}(df, cols)'.format(f)
setup = 'from __main__ import {}, df, cols'.format(f)
tvalue = timeit(stmt, setup, number=500)
results.set_value((n, m), f, tvalue)
从每个方法发生的事情的角度绘制results
,因为我们提取的列数增加。
fig, axes = plt.subplots(2, 2, figsize=(8, 6))
for i, n in enumerate(sizes.levels[0]):
ax = axes[i // 2, i % 2]
results.xs(n).plot(lw=2, ax=ax, title='size {}'.format(n))
ax.legend().remove()
axes[-1, -1].legend(bbox_to_anchor=(1.7, 2.4), fontsize=10)
fig.suptitle('Num Columns Perspective', fontsize=10)
fig.tight_layout()
plt.subplots_adjust(top=.9)
然后从增长数组长度的角度来看
fig, axes = plt.subplots(3, 2, figsize=(8, 9))
for i, m in enumerate(sizes.levels[1]):
ax = axes[i // 2, i % 2]
results.xs(m, level=1).plot(lw=2, ax=ax, title='num cols {}'.format(m), rot=45)
ax.legend().remove()
axes[-1, -1].legend(bbox_to_anchor=(1.7, 4.1), fontsize=10)
fig.suptitle('Array Length Perspective', fontsize=10)
fig.tight_layout()
plt.subplots_adjust(top=.9)
答案 1 :(得分:1)
这是通过使用np.searchsorted
对应给定字符串索引获取列整数索引的方法 -
def linear_index(df, cols):
r,c = df.columns.levels
d0 = np.array([i[0] for i in cols])
d1 = np.array([i[1] for i in cols])
# Skip getting the argsorts if column names are already sorted
r_sidx = r.argsort()
c_sidx = c.argsort()
return np.searchsorted(r,d0,sorter = r_sidx)*len(c) + \
np.searchsorted(c,d1, sorter=c_sidx)
def searchsorted_loc(df, cols):
return df.values[:, linear_index(df, cols)]
这适用于multi-index
数据框。使用一个级别的数据帧时,它会简化。