ডেটাফ্রেম সারিগুলি সাফ করুন


437

আমার কাছে নিম্নলিখিত ডেটা ফ্রেম রয়েছে:

    Col1  Col2  Col3  Type
0      1     2     3     1
1      4     5     6     1
...
20     7     8     9     2
21    10    11    12     2
...
45    13    14    15     3
46    16    17    18     3
...

ডেটাফ্রেম একটি সিএসভি ফাইল থেকে পড়া হয়। Type1 টি থাকা সমস্ত সারি শীর্ষে রয়েছে, তারপরে Type2 দিয়ে সারি এবং তারপরে Type3 দিয়ে সারি থাকবে etc.

আমি ডেটাফ্রেমের সারিগুলির ক্রমটি পরিবর্তন করতে চাই, যাতে সমস্ত Typeমিশ্রিত হয়। একটি সম্ভাব্য ফলাফল হতে পারে:

    Col1  Col2  Col3  Type
0      7     8     9     2
1     13    14    15     3
...
20     1     2     3     1
21    10    11    12     2
...
45     4     5     6     1
46    16    17    18     3
...

আমি কীভাবে এটি অর্জন করতে পারি?

উত্তর:


828

.sampleপান্ডাদের সাথে এটি করার অদ্ভুত উপায়টি হ'ল প্রতিস্থাপন ছাড়াই সমস্ত সারি নমুনার জন্য আপনার ডেটাফ্রেমের পদ্ধতিটি ব্যবহার করা :

df.sample(frac=1)

fracশব্দ যুক্তি নির্দিষ্ট করে সারি ভগ্নাংশ র্যান্ডম নমুনা ফিরে আসতে, তাই frac=1মানে সব সারি ফিরুন (র্যান্ডম ক্রম)।


দ্রষ্টব্য: আপনি যদি নিজের ডেটাফ্রেমকে জায়গায় স্থানান্তর করতে চান এবং সূচকটি পুনরায় সেট করতে চান তবে আপনি যেমন করতে পারেন could

df = df.sample(frac=1).reset_index(drop=True)

এখানে, পুরানো সূচক এন্ট্রি যুক্ত কলাম তৈরি করা নির্দিষ্ট করে drop=Trueবাধা দেয় .reset_index

ফলো-আপ দ্রষ্টব্য: যদিও এটি উপরের অপারেশনটি স্থানে রয়েছে বলে মনে হচ্ছে না তবুও পাইথন / পান্ডাস এলোমেলোভাবে স্মার্ট যে শিফলেড অবজেক্টের জন্য অন্য কোনও ম্যালোক না করে। এটি, যদিও রেফারেন্স অবজেক্টটি পরিবর্তিত হয়েছে (যার দ্বারা আমি বোঝাতে চাইছি id(df_old)এটি একই নয় id(df_new)) তবে অন্তর্নিহিত সি অবজেক্টটি এখনও একই। সত্যই এটির ঘটনাটি প্রমাণ করতে আপনি একটি সাধারণ মেমরি প্রোফাইলার চালাতে পারেন:

$ python3 -m memory_profiler .\test.py
Filename: .\test.py

Line #    Mem usage    Increment   Line Contents
================================================
     5     68.5 MiB     68.5 MiB   @profile
     6                             def shuffle():
     7    847.8 MiB    779.3 MiB       df = pd.DataFrame(np.random.randn(100, 1000000))
     8    847.9 MiB      0.1 MiB       df = df.sample(frac=1).reset_index(drop=True)

6
হ্যাঁ, আমি আমার প্রথম মন্তব্যে ঠিক এটিই দেখাতে চেয়েছিলাম, আপনাকে প্রয়োজনীয় মেমরিটি দু'বার নির্ধারণ করতে হবে, যা এটি জায়গায় করা থেকে বেশ দূরে।
এম-ডিজে

2
@ মি-ডিজে আমি ভুল হলে আমাকে সংশোধন করুন, তবে আপনি যদি তা না করেন তবে .copy()আপনি এখনও একই অন্তর্নিহিত অবজেক্টটি উল্লেখ করছেন।
ক্রিস

2
ঠিক আছে, আমি সময় পেলে এটি একটি মেমরির প্রোফাইল দিয়ে চালাব। ধন্যবাদ
ক্রিস

5
না, এটি ডেটা ফ্রেমের অনুলিপি করে না, কেবল এই লাইনটি দেখুন: github.com/pandas-dev/pandas/blob/v0.23.0/pandas/core/…
minhle_r7

2
@ এম-ডিজে আমি এতে একটি মেমরি প্রোফাইলার চালিয়েছি। আপডেট হওয়া উত্তরে "ফলো-আপ নোট" দেখুন।
ক্রিস

225

আপনি এটির জন্য সহজেই স্কলারন ব্যবহার করতে পারেন

from sklearn.utils import shuffle
df = shuffle(df)

11
এটি দুর্দান্ত, তবে আপনাকে বদলানোর পরে আপনার সূচিগুলি পুনরায় সেট করতে হবে: df.reset_index (অন্তর্ভুক্ত = সত্য, ড্রপ = সত্য)
সেমসাজার

55

আপনি একটি শ্যাফলেড সূচকটি সূচী দিয়ে ডেটাফ্রেমের সারিগুলিকে পরিবর্তন করতে পারেন। এর জন্য, আপনি উদাহরণস্বরূপ ব্যবহার করতে পারেন np.random.permutation(তবে np.random.choiceএটি একটি সম্ভাবনাও):

In [12]: df = pd.read_csv(StringIO(s), sep="\s+")

In [13]: df
Out[13]: 
    Col1  Col2  Col3  Type
0      1     2     3     1
1      4     5     6     1
20     7     8     9     2
21    10    11    12     2
45    13    14    15     3
46    16    17    18     3

In [14]: df.iloc[np.random.permutation(len(df))]
Out[14]: 
    Col1  Col2  Col3  Type
46    16    17    18     3
45    13    14    15     3
20     7     8     9     2
0      1     2     3     1
1      4     5     6     1
21    10    11    12     2

আপনি যদি উদাহরণস্বরূপ 1, 2, .., n থেকে সূচকে নম্বর বজায় রাখতে চান তবে আপনি কেবল সূচকটি পুনরায় সেট করতে পারেন: df_shuffled.reset_index(drop=True)


40

টিএল; ডিআর : np.random.shuffle(ndarray)কাজটি করতে পারে।
সুতরাং, আপনার ক্ষেত্রে

np.random.shuffle(DataFrame.values)

DataFrameহুডের নীচে, ডেটা ধারক হিসাবে NumPy ndarray ব্যবহার করে। (আপনি ডেটা ফ্রেমের উত্স কোড থেকে চেক করতে পারেন )

সুতরাং আপনি যদি ব্যবহার করেন তবে np.random.shuffle()এটি মাল্টি-ডাইমেনশনাল অ্যারের প্রথম অক্ষ বরাবর অ্যারেটিকে বদলে দেবে। তবে DataFrameঅবশেষের সূচকগুলি আনসফুলড রয়েছে।

যদিও, কিছু বিষয় বিবেচনা করার আছে।

  • ফাংশন কিছুই দেয় না। আপনি যদি আসল অবজেক্টের একটি অনুলিপি রাখতে চান তবে ফাংশনে যাওয়ার আগে আপনাকে তা করতে হবে।
  • sklearn.utils.shuffle()ব্যবহারকারী হিসাবে tj89 পরামর্শ হিসাবে, random_stateআউটপুট নিয়ন্ত্রণের জন্য অন্য বিকল্পের সাথে নাম নির্ধারণ করতে পারে। আপনি এটি ডেভ উদ্দেশ্যে করতে পারেন।
  • sklearn.utils.shuffle()দ্রুততর. কিন্তু অক্ষ তথ্য (সূচক, কলাম) অদলবদল করবে DataFrameবরাবর ndarrayএটা রয়েছে।

বেঞ্চমার্ক ফলাফল

মধ্যে sklearn.utils.shuffle()এবং np.random.shuffle()

ndarray

nd = sklearn.utils.shuffle(nd)

0.10793248389381915 সেকেন্ড। 8x দ্রুত

np.random.shuffle(nd)

0.8897626010002568 সেকেন্ড

DataFrame

df = sklearn.utils.shuffle(df)

0.3183923360193148 সেকেন্ড 3x দ্রুত

np.random.shuffle(df.values)

0.9357550159329548 সেকেন্ড

উপসংহার: যদি অক্ষর তথ্য (সূচী, কলাম) নাদারের সাথে বরাবর পরিবর্তন করা ঠিক থাকে তবে ব্যবহার করুন sklearn.utils.shuffle()। অন্যথায়, ব্যবহার করুনnp.random.shuffle()

ব্যবহৃত কোড

import timeit
setup = '''
import numpy as np
import pandas as pd
import sklearn
nd = np.random.random((1000, 100))
df = pd.DataFrame(nd)
'''

timeit.timeit('nd = sklearn.utils.shuffle(nd)', setup=setup, number=1000)
timeit.timeit('np.random.shuffle(nd)', setup=setup, number=1000)
timeit.timeit('df = sklearn.utils.shuffle(df)', setup=setup, number=1000)
timeit.timeit('np.random.shuffle(df.values)', setup=setup, number=1000)


3
না df = df.sample(frac=1)সঠিক একই জিনিস হিসেবে df = sklearn.utils.shuffle(df)? আমার পরিমাপ অনুসারে df = df.sample(frac=1)দ্রুত এবং ঠিক একই ক্রিয়া সম্পাদন করে বলে মনে হচ্ছে। তারা উভয়ই নতুন স্মৃতি বরাদ্দ করে। np.random.shuffle(df.values)এটি সবচেয়ে ধীর, তবে নতুন মেমরি বরাদ্দ করে না।
লো tolmencre

2
ডেটা সহ অক্ষটি বদলানোর ক্ষেত্রে এটি দেখে মনে হচ্ছে এটি একই কাজ করতে পারে। এবং হ্যাঁ, উপরের একই কোডটি ব্যবহার করে দেখে মনে df.sample(frac=1)হয় এটি প্রায় 20% দ্রুত sklearn.utils.shuffle(df)। অথবা আপনি sklearn.utils.shuffle(ndarray)বিভিন্ন ফলাফল পেতে পারে।
হাকু

12

(শীর্ষ পোস্টে এটি মন্তব্য করার মতো যথেষ্ট খ্যাতি আমার নেই, তাই আমি আশা করি অন্য কেউ আমার জন্য এটি করতে পারে।) উদ্বেগ উত্থাপিত হয়েছিল যে প্রথম পদ্ধতি:

df.sample(frac=1)

একটি গভীর অনুলিপি তৈরি করেছে বা স্রেফ ডেটা ফ্রেম পরিবর্তন করেছে। আমি নিম্নলিখিত কোডটি চালিয়েছি:

print(hex(id(df)))
print(hex(id(df.sample(frac=1))))
print(hex(id(df.sample(frac=1).reset_index(drop=True))))

এবং আমার ফলাফলগুলি ছিল:

0x1f8a784d400
0x1f8b9d65e10
0x1f8b9d65b70

যার অর্থ পদ্ধতিটি একই বস্তুটি ফিরিয়ে দিচ্ছে না , যেমনটি শেষ মন্তব্যে পরামর্শ দেওয়া হয়েছিল। সুতরাং এই পদ্ধতিটি সত্যই একটি বদলানো অনুলিপি করে


2
আসল উত্তরের ফলো-আপ নোটটি দয়া করে একবার দেখুন । সেখানে আপনি দেখতে পাবেন যে যদিও রেফারেন্স পরিবর্তিত হয়েছে (বিভিন্ন idগুলি), অন্তর্নিহিত বস্তুর না অনুলিপি করা হয়েছে। অন্য কথায়, অপারেশনটি কার্যকরভাবে মেমোরি হয় (যদিও স্বীকার যে এটি সুস্পষ্ট নয়)।
ক্রিস

7

কী দরকারী, আপনি যদি এটি মেশিন_আরওয়ানিংয়ের জন্য ব্যবহার করেন এবং সর্বদা একই ডেটা আলাদা করতে চান তবে আপনি ব্যবহার করতে পারেন:

df.sample(n=len(df), random_state=42)

এটি নিশ্চিত করে তোলে যে আপনি নিজের এলোমেলো পছন্দ সর্বদা প্রতিরূপযোগ্য রাখবেন


5

আফিকের সহজ সমাধানটি হ'ল:

df_shuffled = df.reindex(np.random.permutation(df.index))

3
দয়া করে লক্ষ্য করুন যে এটি সূচকগুলি মূল df- তে পরিবর্তিত করে পাশাপাশি একটি অনুলিপি তৈরি করে যা আপনি df_shuffled এ সংরক্ষণ করছেন। তবে, এটি আরও উদ্বেগজনক যে কোনও কিছু যা সূচকে নির্ভর করে না, উদাহরণস্বরূপ `df_shuffled.iterrows () 'df এর মতো ঠিক একই ক্রম উত্পাদন করবে। সংক্ষেপে, সাবধানতার সাথে ব্যবহার করুন!
Jblasco

@ জাব্লাস্কো এটি ভুল, মূল ডিএফ মোটেও পরিবর্তন করা হয়নি। এর ডকুমেন্টেশন np.random.permutation: "... এক্স যদি অ্যারে হয় তবে একটি অনুলিপি তৈরি করুন এবং উপাদানগুলি এলোমেলোভাবে বদল করুন"। এর ডকুমেন্টেশন DataFrame.reindex: " নতুন সূচকটি বর্তমান সূচকের সমতুল্য না হলে এবং অনুলিপি = মিথ্যা" তৈরি করা হলে একটি নতুন অবজেক্ট উত্পন্ন হয়। সুতরাং উত্তরটি পুরোপুরি নিরাপদ (একটি অনুলিপি তৈরি করা হলেও)।
Andreas Schörgenhumer

3
@ আন্ড্রেস শ্যার্জেনহুমার, এটি দেখানোর জন্য আপনাকে ধন্যবাদ, আপনি আংশিকভাবে ঠিক আছেন! আমি জানতাম যে আমি এটি চেষ্টা করেছি, তাই আমি কিছু পরীক্ষা করেছি। ডকুমেন্টেশনের যা আছে np.random.permutation saysএবং স্নিগ্ধ সংস্করণের উপর নির্ভর করে সত্ত্বেও, আপনি আমার বর্ণিত প্রভাবটি বা আপনার উল্লেখ করা একটি প্রভাব পান। নপি> 1.15.0 এর সাথে একটি ডেটাফ্রেম তৈরি করে এবং একটি সরল কাজ np.random.permutation(df.index)করে সূচকগুলি মূল ডিএফ পরিবর্তন করে। অকার্যকর == 1.14.6 এর ক্ষেত্রেও এটি একই নয়। সুতরাং, আগের চেয়ে আমি আমার সতর্কবার্তাটির পুনরাবৃত্তি করেছি: অপ্রত্যাশিত পার্শ্ব প্রতিক্রিয়া এবং সংস্করণ নির্ভরতার কারণে জিনিসগুলি করার উপায়টি বিপজ্জনক।
Jblasco

@ জাব্লাস্কো আপনি ঠিক বলেছেন, বিশদটির জন্য আপনাকে ধন্যবাদ। আমি ছদ্মবেশী 1.14 চালাচ্ছি, তাই সবকিছু ঠিকঠাক কাজ করেছে। নপি 1.15 সহ কোথাও একটি বাগ রয়েছে বলে মনে হচ্ছে । এই বাগের আলোকে, আপনার সতর্কতাগুলি বর্তমানে সত্যই সঠিক। তবে এটি যেহেতু একটি বাগ এবং ডকুমেন্টেশনটি অন্য আচরণের বিবরণ দেয়, আমি এখনও আমার আগের বক্তব্যটির সাথে লেগে থাকি যে উত্তরটি নিরাপদ (ডকুমেন্টেশনটি প্রকৃত আচরণকে প্রতিফলিত করে, যা আমরা সাধারণত নির্ভর করতে পারি)।
Andreas Schörgenhumer

@ আন্দ্রেস শ্যাগারজেনহুমার, সত্যই নিশ্চিত হন না যে এটি কোনও বাগ বা কোনও বৈশিষ্ট্য কিনা। ডকুমেন্টেশন একটি অ্যারের অনুলিপি, কোনও Indexধরণের নয় ... কোনও ক্ষেত্রেই, আমি আমার প্রস্তাবনাগুলি / সতর্কতাগুলিকে ডক্সের উপর নির্ভর করে না, প্রকৃত আচরণের উপর ভিত্তি করে দেখি: p
Jblasco

2

এই ক্ষেত্রে একটি নমুনা বিন্যাস গ্রহণ করে পান্ডাস ডেটা ফ্রেম এলোমেলো সূচক এবং এলোমেলো তার আদেশ তারপর ডাটা ফ্রেমের একটি সূচক যেমন অ্যারে সেট। এখন সূচি অনুসারে ডেটা ফ্রেমকে সাজান। এখানে আপনার বদলানো ডেটা ফ্রেম যায় ra

import random
df = pd.DataFrame({"a":[1,2,3,4],"b":[5,6,7,8]})
index = [i for i in range(df.shape[0])]
random.shuffle(index)
df.set_index([index]).sort_index()

আউটপুট

    a   b
0   2   6
1   1   5
2   3   7
3   4   8

উপরের কোডটিতে আমার জায়গায় আপনাকে ডেটা ফ্রেম .োকান।


আমি এই পদ্ধতিটিকে পছন্দ করি কারণ এর অর্থ হল যদি আমার অ্যালগরিদম আউটপুটকে ঠিক পুনরুত্পাদন করতে হয় তবে এলোমেলোভাবে সূচকটি একটি চলকতে সংরক্ষণ করে the
রায়জিনজ

0

এখানে অন্য উপায়:

df['rnd'] = np.random.rand(len(df)) df = df.sort_values(by='rnd', inplace=True).drop('rnd', axis=1)

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