آموزش Numpy: بخش سوم

آموزش Numpy: بخش سوم

maxresdefault
آموزش پیشرفته پایتون

آموزش Numpy: بخش سوم

import numpy as np

# فرض کن دو تا ماتریس با ۲ سطر و ۳ ستون داریم
A = np.array([[1, 2, 3],
              [4, 5, 6]])

B = np.array([[7, 8, 9],
              [10, 11, 12]])

# چسباندن عمودی: B زیر A قرار می‌گیرد
result = np.vstack((A, B))

print("نتیجه vstack (ابعاد 4x3 می‌شود):\n", result)
# خروجی:
# [[ 1  2  3]
#  [ 4  5  6]
#  [ 7  8  9]
#  [10 11 12]]
# دو ماتریس با ۲ سطر، ولی تعداد ستون‌های متفاوت
A = np.array([[1, 2],
              [3, 4]])        # ابعاد: (2, 2)

B = np.array([[5, 6, 7],
              [8, 9, 10]])    # ابعاد: (2, 3)

# چسباندن افقی: B در سمت راست A قرار می‌گیرد
result = np.hstack((A, B))

print("نتیجه hstack (ابعاد 2x5 می‌شود):\n", result)
# خروجی:
# [[ 1  2  5  6  7]
#  [ 3  4  8  9 10]]
A = np.array([[1, 2],
              [3, 4]])

B = np.array([[5, 6],
              [7, 8]])

# ۱. اتصال عمودی (سوار کردن روی هم با axis=0)
concat_axis0 = np.concatenate((A, B), axis=0)
print("اتصال با axis=0:\n", concat_axis0)
# خروجی (4x2):
# [[1 2]
#  [3 4]
#  [5 6]
#  [7 8]]

# ۲. اتصال افقی (گذاشتن کنار هم با axis=1)
concat_axis1 = np.concatenate((A, B), axis=1)
print("\nاتصال با axis=1:\n", concat_axis1)
# خروجی (2x4):
# [[1 2 5 6]
#  [3 4 7 8]]
# دو بردار یک‌بعدی (هر کدام ۳ عضو دارند)
a = np.array([1, 2, 3])  # شکل: (3,)
b = np.array([4, 5, 6])  # شکل: (3,)

# حالت اول: با concatenate بعد جدید ساخته نمی‌شود
c = np.concatenate((a, b))
print("شکل با concatenate:", c.shape)  # خروجی: (6,) - همان ۱ بعدی باقی ماند

# حالت دوم: با stack یک بعد جدید متولد می‌شود!
s0 = np.stack((a, b), axis=0)
print("شکل با stack (axis=0):", s0.shape)  # خروجی: (2, 3) - تبدیل به ۲ بعدی شد!
print("محتوا:\n", s0)

s1 = np.stack((a, b), axis=1)
print("شکل با stack (axis=1):", s1.shape)  # خروجی: (3, 2)
print("محتوا:\n", s1)
# یک ماتریس ۴ در ۴ بسازیم
matrix = np.array([
    [10, 20, 30, 40],
    [50, 60, 70, 80],
    [11, 22, 33, 44],
    [55, 66, 77, 88]
])

# ۱. برش عمودی (vsplit): تقسیم سطرها به دو بخش بالا و پایین
top, bottom = np.vsplit(matrix, 2)
print("بخش بالایی (vsplit):\n", top)
print("بخش پایینی (vsplit):\n", bottom)

# ۲. برش افقی (hsplit): تقسیم ستون‌ها به دو بخش چپ و راست
left, right = np.hsplit(matrix, 2)
print("\nبخش چپ (hsplit):\n", left)
print("بخش راست (hsplit):\n", right)

# ۳. تابع array_split (بسیار کارآمد وقتی ابعاد بخش‌پذیر نباشند)
# مثلا تقسیم آرایه ۵ عضوی به ۳ بخش (که با split عادی ارور می‌دهد):
arr = np.array([1, 2, 3, 4, 5])
chunks = np.array_split(arr, 3)
print("\nتقسیم نامتقارن:", chunks)
# آرایه اصلی
original = np.array([10, 20, 30, 40])

# ==========================================
# سناریوی اول: خطر نما (View) با استفاده از Slicing
# ==========================================
view_arr = original[0:2]  # فقط یک نماست!
view_arr[0] = 999          # تغییر روی نما

print("تغییر روی نما انجام شد.")
print("آرایه فرعی:", view_arr)
print("آرایه اصلی دستکاری شد!:", original)  # مقدار اول 999 شده!


# ==========================================
# سناریوی دوم: راه حل امن؛ ساخت کپی مستقل با .copy()
# ==========================================
original = np.array([10, 20, 30, 40])

safe_copy = original[0:2].copy()  # حافظه کاملاً جداگانه
safe_copy[0] = 777                # تغییر روی کپی

print("\nتغییر روی کپی امن انجام شد.")
print("آرایه کپی شده:", safe_copy)
print("آرایه اصلی دست‌نخورده باقی ماند:", original)  # همان [10, 20, 30, 40]

# بررسی مالکیت حافظه با ویژگی base
print(view_arr.base is original)   # True: یعنی این صرفاً یک نما از original است!
print(safe_copy.base is None)      # True: یعنی حافظه مال خودش است و مستقل است!

# فرض کن نمرات یک کلاس را داری
scores = np.array([12, 18, 8, 15, 9, 20])

# می‌خواهیم نمرات زیر ۱۰ را "مردود" و ۱۰ به بالا را "قبول" کنیم
status = np.where(scores >= 10, "قبول", "مردود")

print("نمرات اصلی:", scores)
print("وضعیت دانش‌آموزان:", status)
# خروجی: ['قبول' 'قبول' 'مردود' 'قبول' 'مردود' 'قبول']


# یک مثال کاربردی دیگر: کپ کردن (Limit) مقادیر پرتی که از حد مجاز بالاترند
# اگر عددی از ۱۵ بزرگتر بود، بکنش ۱۵؛ وگرنه خود عدد بمونه
clipped_scores = np.where(scores > 15, 15, scores)
print("نمرات تعدیل‌شده:", clipped_scores)
arr = np.array([10, 50, 20, 80, 30])

# پیدا کردن اندیس عناصری که از ۳۰ بزرگتر هستند
indices = np.where(arr > 30)

print("اندیس مقادیر بزرگتر از ۳۰:", indices[0]) # خروجی: [1, 3]
print("خود آن مقادیر:", arr[indices])          # خروجی: [50, 80]
data = np.array([10.0, np.nan, 25.0, np.nan, 50.0])

# بررسی وجود NaN (خروجی یک آرایه بولین است)
print("آیا NaN هست؟:", np.isnan(data))
# خروجی: [False  True False  True False]

# شمارش تعداد داده‌های گمشده
print("تعداد NaNها:", np.isnan(data).sum()) # خروجی: 2
data = np.array([10.0, np.nan, 20.0, 30.0])

# تابع عادی (خراب می‌شود!)
print("میانگین با تابع عادی:", np.mean(data)) # خروجی: nan

# تابع امن (NaN را نادیده می‌گیرد و میانگین ۱۰، ۲۰ و ۳۰ را حساب می‌کند)
print("میانگین امن (nanmean):", np.nanmean(data)) # خروجی: 20.0
print("مجموع امن (nansum):", np.nansum(data))     # خروجی: 60.0
data = np.array([10.0, np.nan, 30.0, np.nan, 50.0])

# محاسبه میانگین داده‌های معتبر
mean_val = np.nanmean(data)

# جایگزینی NaNها با میانگین محاسبه‌شده
cleaned_data = np.where(np.isnan(data), mean_val, data)

print("داده‌های پاک‌سازی‌شده با میانگین:", cleaned_data)
# خروجی: [10. 30. 30. 30. 50.]
import numpy as np

data = np.array([10.0, np.nan, np.inf])

# به‌طور خودکار NaN را با 0 و Inf را با یک عدد بسیار بزرگ جایگزین می‌کند
clean_quick = np.nan_to_num(data, nan=0.0, posinf=9999.0)

print("جایگزینی سریع:", clean_quick)
# خروجی: [  10.    0. 9999.]
# فرض کن یک آرایه از ویژگی‌ها یا سیگنال‌ها داریم
data = np.random.rand(100, 3)

# ۱. ذخیره آرایه روی دیسک (پسوند npy به طور خودکار اضافه می‌شود)
np.save("features.npy", data)

# ۲. بارگذاری مجدد از دیسک
loaded_data = np.load("features.npy")

print("شکل داده بارگذاری شده:", loaded_data.shape)
print("آیا داده اولیه با داده لود شده برابر است؟", np.array_equal(data, loaded_data))

مزیت بزرگ .npy: لود کردن یک فایل باینری ۱۰ گیگابایتی در نامپای معمولاً چند ثانیه بیشتر طول نمی‌کشد، در حالی که لود کردن همین حجم به صورت متنی یا CSV ممکن است دقیقه‌ها طول بکشد و کل رم را منفجر کند!

X_train = np.random.rand(80, 10)
y_train = np.random.randint(0, 2, 80)

# ذخیره فشرده چند آرایه با نام‌گذاری دلخواه
np.savez_compressed("dataset.npz", features=X_train, labels=y_train)

# بارگذاری فایل فشرده
dataset = np.load("dataset.npz")

# دسترسی به آرایه‌ها مانند یک دیکشنری در پایتون
print("نام آرایه‌های ذخیره شده:", dataset.files)
loaded_X = dataset["features"]
loaded_y = dataset["labels"]

print("ابعاد ویژگی‌ها:", loaded_X.shape)
print("ابعاد برچسب‌ها:", loaded_y.shape)

data = np.array([
    [10.5, 20.2, 30.1],
    [40.8, 50.4, 60.9]
])

# ذخیره به صورت فایل متنی با جداکننده کاما (CSV)
# پارامتر fmt='%.2f' یعنی اعداد را تا ۲ رقم اعشار ذخیره کن
np.savetxt("output.csv", data, delimiter=",", fmt="%.2f", header="col1,col2,col3", comments="")

# بارگذاری مجدد از فایل متنی
loaded_csv = np.loadtxt("output.csv", delimiter=",", skiprows=1)
print("داده بارگذاری شده از CSV:\n", loaded_csv)

# ۱. اضافه و کم کردن بعد (newaxis و squeeze)
x = np.array([10, 20, 30])           # shape: (3,)
x_2d = x[:, np.newaxis]              # shape: (3, 1) -> ماتریس ستونی
x_back = np.squeeze(x_2d)            # shape: (3,)   -> برگشت به بردار

# ۲. جادوی argsort (پیدا کردن رتبه داده‌ها به جای خود داده)
scores = np.array([0.15, 0.85, 0.40])
print("اندیس به ترتیب صعودی:", np.argsort(scores)) # [0, 2, 1]

# ۳. شمارش کلاس‌ها با unique
labels = np.array([0, 1, 1, 0, 2, 1, 0])
classes, counts = np.unique(labels, return_counts=True)
print("کلاس‌ها:", classes)   # [0 1 2]
print("فراوانی:", counts)    # [3 3 1]

# ۴. مهار کردن داده‌های پرت با clip
raw_vals = np.array([-5, 12, 150, 300, 45])
print("مهار شده:", np.clip(raw_vals, 0, 100)) # [  0  12 100 100  45]

فکر خود را اینجا بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *