Pandas Dataframe Performance应用了shift功能

时间:2017-12-29 21:32:05

标签: python performance pandas numpy profiling

我正在尝试优化我的代码。一个电话很快,但因为我经常遇到一些问题。

我的输入数据如下所示:

public function product()
{
    return $this->belongsTo('App\Product');
}

现在我只想申请一个简单的功能。以下是我想要优化的部分:

public void setClickListener(View.OnClickListener callback) {
    mClickListener = callback;
}

public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) 
{
    if (viewType == AD_TYPE) {
        View inflatedView;
        if (AD_FORM == 3) {
            inflatedView = LayoutInflater.from(viewGroup.getContext())
                    .inflate(R.layout.ad_unit, viewGroup, false);
        }
        else {
            inflatedView = LayoutInflater.from(viewGroup.getContext())
                    .inflate(R.layout.ad_unit2, viewGroup, false);
        }
        return new AdHolder(inflatedView);
    }
    else {
        View inflatedView = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.feed_item, viewGroup, false);
        PersonViewHolder personViewHolder = new PersonViewHolder(inflatedView);
        personViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mClickListener.onClick(view);
            }
        });
        return personViewHolder;
    }
}

public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) 
{
    if (holder.getItemViewType() == AD_TYPE) {
        if (mAd != null) {
            ((AdHolder)holder).bindView(mAd);
        }
        else if (mAds != null && mAds.isLoaded()) {
            mAd = mAds.nextNativeAd();
            ((AdHolder)holder).bindView(mAd);
        }
        else {
            ((AdHolder)holder).bindView(null);
        }
    }
    else {
        i = position;
        if (i != 0) {
            i--;
        }
        String cover = "https://www.stanzascoop.com/covers/"+ persons.get(i).photoId;
        String avi = "https://www.stanzascoop.com/avis/"+ persons.get(i).photo;
        final String views = NumberFormat.getInstance().format(persons.get(i).viewcount) + " scoops";
        ((PersonViewHolder)holder).uploadUser.setText(persons.get(i).username);
        ((PersonViewHolder)holder).uploadDate.setText(persons.get(i).uploaddate);
        ((PersonViewHolder)holder).personName.setText(persons.get(i).name);
        ((PersonViewHolder)holder).personAge.setText("by "+ persons.get(i).age);
        ((PersonViewHolder)holder).viewCount.setText(views);
        context = mContext;
        Picasso.with(context).load(cover).transform(new RoundedTransformation(0, 0)).fit().into(((PersonViewHolder)holder).personPhoto);
        Picasso.with(context).load(avi).transform(new RoundedTransformation(100, 0)).fit().into(((PersonViewHolder)holder).authorPhoto);

        ((PersonViewHolder)holder).setClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int s = getItemCount();
                int pos = ((PersonViewHolder)holder).getAdapterPosition();
                Log.e(TAG, "POS: "+ ((PersonViewHolder)holder).getItemId());
                openLyric(persons.get(i).name, persons.get(i).content, persons.get(i).age, persons.get(i).photoId, views, persons.get(i).lurl);
            }
        });

    }
}

现在我得到1000个循环,最好的3个:每个循环1.36毫秒。我想应该可以更快地做到这一点。不确定我是否应该进行矢量化,只能使用numpy或者使用cython。最好的方法是什么想法?我和班次操作员有点挣扎。

3 个答案:

答案 0 :(得分:1)

您可以将比较结果直接从bool转换为int

(df >= df.shift(1)).astype(int)

答案 1 :(得分:0)

这是我目前最好的解决方案:

values = df.values[1:] >= df.values[:-1] 
data = np.array(values, dtype=int)
s  = pd.DataFrame(data, df.index[1:])

我得到10000个循环,最好是每个循环3:125μs。 x10改进。但我认为它可以做得更快。

PS:这个解决方案并不完全正确,因为缺少第一个零/ nan。 PPS:可以通过pd.DataFrame(np.append([[0]],data),df.index)来修正

答案 2 :(得分:0)

@Paul H的答案很好,性能也很好,我一般都会推荐。

也就是说,如果你想挤出最后一点性能,这是numba的一个不错的选择,你可以用它来计算一次通过数据的答案。

from numba import njit

@njit
def do_calc(arr):
    N = arr.shape[0]
    ans = np.empty(N, dtype=np.int_)
    ans[0] = 0
    for i in range(1, N):
        ans[i] = 1 if arr[i] > arr[i-1] else 0
    return ans

a = (df >= df.shift(1)).astype(int)
b = pd.DataFrame(pd.Series(do_calc(df[0].values), df[0].index))

from pandas.testing import assert_frame_equal
assert_frame_equal(a, b)

这是时间

In [45]: %timeit b = pd.DataFrame(pd.Series(do_calc(df[0].values), df[0].index))
135 µs ± 1.83 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [46]: %timeit a = (df >= df.shift(1)).astype(int)
762 µs ± 22.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)