দক্ষতার সাথে দুই কলামে তালিকাগুলির তুলনা করুন wise


16

কোনও পান্ডাস ডেটা ফ্রেম থাকার সময়:

import pandas as pd
import numpy as np
df = pd.DataFrame({'today': [['a', 'b', 'c'], ['a', 'b'], ['b']], 
                   'yesterday': [['a', 'b'], ['a'], ['a']]})
                 today        yesterday
0      ['a', 'b', 'c']       ['a', 'b']
1           ['a', 'b']            ['a']
2                ['b']            ['a']                          
... etc

তবে প্রায় 100,000 এন্ট্রি সহ, আমি সারি অনুসারে দুটি কলামে সেই তালিকাগুলির সংযোজন এবং অপসারণগুলি সন্ধান করছি।

এটি এই প্রশ্নের সাথে তুলনীয়: পান্ডস: কীভাবে পান্ডাদের (লুপের জন্য নয়) একটি ডেটা ফ্রেমে সারি অনুসারে তালিকাগুলির তালিকাগুলি তুলনা করবেন? তবে আমি পার্থক্যগুলি দেখছি, এবং Pandas.applyএমন অনেকগুলি এন্ট্রিগুলির জন্য পদ্ধতিটি এত দ্রুত নয় বলে মনে হচ্ছে। এই কোডটি আমি বর্তমানে ব্যবহার করছি। Pandas.applyসঙ্গে numpy's setdiff1dপদ্ধতি:

additions = df.apply(lambda row: np.setdiff1d(row.today, row.yesterday), axis=1)
removals  = df.apply(lambda row: np.setdiff1d(row.yesterday, row.today), axis=1)

এটি দুর্দান্ত কাজ করে, তবে এটি 120 000 এন্ট্রিগুলির জন্য প্রায় এক মিনিট সময় নেয়। তাহলে এটি সম্পাদন করার আরও দ্রুত উপায় আছে?


এই কলামগুলির মধ্যে একটিতে সর্বোচ্চ কতগুলি আইটেম (একক সারিতে) থাকতে পারে?
thushv89

2
আপনি যে পোস্টটি লিঙ্ক করেছেন সে পদ্ধতিতে আপনি কি চেষ্টা করেছেন? বিশেষত যা সেট ছেদ ব্যবহার করে, আপনাকে যা করতে হবে তার পরিবর্তে সেট পার্থক্য ব্যবহার করা উচিত, না?
স্বর্ণ_দুপুর

1
@aws_apprentice যে সমাধানটি এখানে মূলত ওপি-র রয়েছে is
কোয়াং হোয়াং

কোনও পান্ডাস ডেটা ফ্রেম এর জন্য সঠিক ডেটা কাঠামো নাও হতে পারে। আপনি কি প্রোগ্রাম এবং ডেটাতে কিছুটা বেশি পটভূমি ভাগ করতে পারেন?
এএমসি

উত্তর:


14

পারফরম্যান্স সম্পর্কে নিশ্চিত নয়, তবে এর চেয়ে ভাল সমাধানের অভাবে এটি প্রয়োগ হতে পারে:

temp = df[['today', 'yesterday']].applymap(set)
removals = temp.diff(periods=1, axis=1).dropna(axis=1)
additions = temp.diff(periods=-1, axis=1).dropna(axis=1) 

সরানো:

  yesterday
0        {}
1        {}
2       {a}

সংযোজন:

  today
0   {c}
1   {b}
2   {b}

2
এটি খুব দ্রুত।
আরপানাই

2
এটি আসলে খুব দ্রুত। নেমে এসেছিল প্রায় ২ সেকেন্ড!
মেগা কুকি

2
বাহ, আমি পারফরম্যান্সের কারণেও অবাক হয়েছি applymap, তবে খুশির কারণ এটি আপনার পক্ষে কার্যকর হয়েছে!
r.ook

2
এখন, আমরা যেমন জানি যে রোকসের সমাধানটি দ্রুত, কেউ আমাকে ব্যাখ্যা করতে পারে? কেন এটি দ্রুত ছিল?
গ্রিজেশ চৌহান


5

আমি আপনাকে গণনা করতে additionsএবং removalsএকই প্রয়োগের মধ্যে পরামর্শ দেব ।

আরও বড় উদাহরণ তৈরি করুন

import pandas as pd
import numpy as np
df = pd.DataFrame({'today': [['a', 'b', 'c'], ['a', 'b'], ['b']], 
                   'yesterday': [['a', 'b'], ['a'], ['a']]})
df = pd.concat([df for i in range(10_000)], ignore_index=True)

আপনার সমাধান

%%time
additions = df.apply(lambda row: np.setdiff1d(row.today, row.yesterday), axis=1)
removals  = df.apply(lambda row: np.setdiff1d(row.yesterday, row.today), axis=1)
CPU times: user 10.9 s, sys: 29.8 ms, total: 11 s
Wall time: 11 s

একক প্রয়োগে আপনার সমাধান

%%time
df["out"] = df.apply(lambda row: [np.setdiff1d(row.today, row.yesterday),
                                  np.setdiff1d(row.yesterday, row.today)], axis=1)
df[['additions','removals']] = pd.DataFrame(df['out'].values.tolist(), columns=['additions','removals'])
df = df.drop("out", axis=1)

CPU times: user 4.97 s, sys: 16 ms, total: 4.99 s
Wall time: 4.99 s

ব্যবহার set

আপনার তালিকাগুলি খুব বড় না হলে আপনি এড়াতে পারবেন numpy

def fun(x):
    a = list(set(x["today"]).difference(set(x["yesterday"])))
    b = list((set(x["yesterday"])).difference(set(x["today"])))
    return [a,b]

%%time
df["out"] = df.apply(fun, axis=1)
df[['additions','removals']] = pd.DataFrame(df['out'].values.tolist(), columns=['additions','removals'])
df = df.drop("out", axis=1)

CPU times: user 1.56 s, sys: 0 ns, total: 1.56 s
Wall time: 1.56 s

@ r.ook এর সমাধান

আপনি যদি আউটপুট হিসাবে তালিকার পরিবর্তে সেট রাখলে খুশি হন তবে আপনি @ r.ook এর কোড ব্যবহার করতে পারেন

%%time
temp = df[['today', 'yesterday']].applymap(set)
removals = temp.diff(periods=1, axis=1).dropna(axis=1)
additions = temp.diff(periods=-1, axis=1).dropna(axis=1) 
CPU times: user 93.1 ms, sys: 12 ms, total: 105 ms
Wall time: 104 ms

@ আন্ড্রেস কে এর সমাধান

%%time
df['additions'] = (df['today'].apply(set) - df['yesterday'].apply(set))
df['removals'] = (df['yesterday'].apply(set) - df['today'].apply(set))

CPU times: user 161 ms, sys: 28.1 ms, total: 189 ms
Wall time: 187 ms

এবং শেষ পর্যন্ত .apply(list)আপনার একই আউটপুট পেতে যোগ করতে পারেন


1
আপনি যে দুর্দান্ত তুলনা করেছেন!
মেগা কুকি

1

ভেক্টরাইজড নুমপি সরঞ্জামগুলিতে গণনা অংশ অফলোড করার ধারণাটি এখানে রয়েছে। আমরা প্রতিটি শিরোলেখের জন্য একক অ্যারে সমস্ত ডেটা সংগ্রহ করব, NumPy এ প্রয়োজনীয় সমস্ত মিলটি করবো এবং শেষ পর্যন্ত প্রয়োজনীয় সারি এন্ট্রিগুলিতে ফিরে কাটব। ভারী উত্তোলনের অংশটি করে এমন নুমপিতে, আমরা প্রতিটি গ্রুপের মধ্যে গ্রুপ আইডি এবং আইডি ব্যবহার করে হ্যাশ ব্যবহার করব np.searchsorted। আমরা সংখ্যারও ব্যবহার করছি কারণ এগুলি NumPy এর সাথে দ্রুত। বাস্তবায়নটি এরকম কিছু দেখায় -

t = df['today']
y = df['yesterday']
tc = np.concatenate(t)
yc = np.concatenate(y)

tci,tcu = pd.factorize(tc)

tl = np.array(list(map(len,t)))
ty = np.array(list(map(len,y)))

grp_t = np.repeat(np.arange(len(tl)),tl)
grp_y = np.repeat(np.arange(len(ty)),ty)

sidx = tcu.argsort()
idx = sidx[np.searchsorted(tcu,yc,sorter=sidx)]

s = max(tci.max(), idx.max())+1
tID = grp_t*s+tci
yID = grp_y*s+idx

t_mask = np.isin(tID, yID, invert=True)
y_mask = np.isin(yID, tID, invert=True)

t_se = np.r_[0,np.bincount(grp_t,t_mask).astype(int).cumsum()]
y_se = np.r_[0,np.bincount(grp_y,y_mask).astype(int).cumsum()]

Y = yc[y_mask].tolist()
T = tc[t_mask].tolist()

A = pd.Series([T[i:j] for (i,j) in zip(t_se[:-1],t_se[1:])])
R = pd.Series([Y[i:j] for (i,j) in zip(y_se[:-1],y_se[1:])])

আরও অনুকূলকরণ গণনা করার পদক্ষেপে t_maskএবং y_maskযেখানে np.searchsortedআবার ব্যবহার করা যেতে পারে তা সম্ভব ।

isinপদক্ষেপটি পাওয়ার বিকল্প হিসাবে আমরা একটি সাধারণ অ্যারে-অ্যাসাইনমেন্টও ব্যবহার করতে পারি t_maskএবং এর y_maskমতো -

M = max(tID.max(), yID.max())+1
mask = np.empty(M, dtype=bool)

mask[tID] = True
mask[yID] = False
t_mask = mask[tID]

mask[yID] = True
mask[tID] = False
y_mask = mask[yID]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.