首页
学习
活动
专区
圈层
工具
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

迈向中级数据科学家的Python编程模式:让你的代码更高效、可维护

对于许多数据科学初学者来说,Python 是大家学习和探索的第一门语言。它是一门功能强大的通用语言,能够高效地进行数据处理,因此深受数据从业者的喜爱。

然而,随着实际项目的推进,基础的入门知识已经远远不够。现实问题更加复杂,简单的代码可能无法解决实际需求,代码甚至会变得低效且难以维护和沟通。

如果你希望从初级迈向中级,这一点尤为明显。仅仅学习新的库或复杂的算法是不够的,你还必须通过引入编程模式来优化你的 Python 代码结构和工作流程。

如前所述,从初级到中级数据科学家的转变,并不只是写基础代码。你需要更聪明、更有结构地编写代码。中级阶段的目标是让你的代码更加模块化、可扩展,同时提高代码的可读性和可维护性,能够应对更复杂的工作流。

通过运用各种 Python 编程模式,我们可以极大地提升代码质量和工作流程,远超基础水平。下面,我们将从数据处理流水线模式开始,逐步探讨这些模式。

在本文中,我们将讨论多种 Python 编程模式,助你提升代码水平,迈入中级数据科学家行列。让我们正式开始吧!

数据流水线模式(Data Pipeline Pattern)

在数据处理过程中,我们会遇到诸多任务,如数据清洗、预处理和特征工程。初学者常常在笔记本或脚本中零散处理这些任务,甚至多次重复同样的操作。

如果你持续采用这种方式,调试会变得异常繁琐和困难,同时也会带来巨大的技术债务,影响团队协作。因此,我们需要流水线模式来优化工作流程。

流水线是一种将数据处理步骤按顺序组织起来的过程。我们定义好各个阶段,每个阶段专注于一个特定操作,如数据加载、清洗、缩放、模型训练等。这是一种系统化、逐步推进的过程。

让我们以 Pandas DataFrame 为例,模拟一个销售数据的数据框:

import pandas as pd

import numpy as np

data = {

  'sales': [1000, 1500, np.nan, 2000, 2500],

  'quantity': [50, 60, 70, np.nan, 90],

  'product': ['A', 'B', 'C', 'D', 'E']

}

example_df = pd.DataFrame(data)

作为数据科学家,你可能经常需要执行以下常见的数据处理步骤:数据加载、清洗和特征工程。

# 第一步:加载数据

def load_data(df: pd.DataFrame) -> pd.DataFrame:

  return df

# 第二步:数据清洗

def clean_data(df: pd.DataFrame) -> pd.DataFrame:

  missing_before = df.isnull().sum().sum()

  df_cleaned = df.dropna().reset_index(drop=True)

  missing_after = df_cleaned.isnull().sum().sum()

  return df_cleaned

# 第三步:特征工程

def engineer_features(df: pd.DataFrame) -> pd.DataFrame:

  if 'sales' in df.columns and 'quantity' in df.columns:

      df['avg_price'] = df['sales'] / df['quantity']

  return df

通过将每个数据处理环节封装成可复用的函数,你可以多次执行,而无需每次都手动编写。

不过,为了让结构更加清晰,应该将其做成流水线。下面我们为这些函数创建一个流水线执行函数:

def execute_pipeline(df: pd.DataFrame, steps: list) -> pd.DataFrame:

  for step in steps:

      df = step(df)

  return df

pipeline_steps = [

  load_data,

  clean_data,

  engineer_features

]

final_df = execute_pipeline(example_df, pipeline_steps)

就是这样!通过简单的流水线函数,你就拥有了可复用且易读的代码。

你还可以用 Scikit-Learn 创建数据处理和建模的流水线。以下是相关的概念代码:

from sklearn.pipeline import Pipeline

from sklearn.impute import SimpleImputer

from sklearn.preprocessing import StandardScaler

from sklearn.ensemble import RandomForestClassifier

pipeline = Pipeline([

  ('imputer', SimpleImputer(strategy='mean')),

  ('scaler', StandardScaler()),

  ('classifier', RandomForestClassifier(n_estimators=100, random_state=42))

])

pipeline.fit(X, y)

请善用流水线模式,它对你未来的数据科学任务大有裨益。

工厂模式(Factory Pattern)

区分初级与中级编程能力的关键在于:能否实现代码复用,并尽量少写重复代码。对于数据科学来说,由于流程更复杂、实验更频繁,这一点尤为重要。

在进行数据和模型实验时,我们常常需要频繁切换不同模型和数据集,手动编写代码既繁琐又容易混乱。

此时,工厂模式就非常有用。本质上,工厂模式是将对象的创建(如机器学习模型)集中管理,通过调整参数即可生成不同对象,而无需为每种情况单独写代码。

借助工厂模式,我们可以集中管理对象的创建,轻松进行实验,使代码更加模块化。

来看一个创建机器学习模型的工厂模式例子:

from sklearn.linear_model import LogisticRegression

from sklearn.tree import DecisionTreeClassifier

from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier

def model_factory(model_type: str, **kwargs):

  models = {

      'logistic_regression': LogisticRegression,

      'decision_tree': DecisionTreeClassifier,

      'random_forest': RandomForestClassifier,

      'gradient_boosting': GradientBoostingClassifier

  }

  if model_type not in models:

      raise ValueError(f"Unsupported model type '{model_type}'. Supported types: {list(models.keys())}")

  return models[model_type](**kwargs)

我们只需定义一个函数,通过更改参数即可创建不同的机器学习模型。

然后便可轻松调用函数生成所需模型:

logreg_model = model_factory(

  model_type='logistic_regression',

  solver='liblinear',

  random_state=42)

对于容易混乱的实验环节,建议采用工厂模式进行管理。

装饰器模式(Decorator Pattern)

随着数据工作流的扩展,你可能希望增加如日志记录等额外功能。许多人会在脚本里手动插入日志代码,但这样容易造成冗余,降低代码可读性。

这时可以使用装饰器模式。装饰器是一种特殊函数,用于包装其他函数,在不改变核心逻辑的前提下,给函数添加额外功能。

利用装饰器,可以在多个函数中统一处理附加功能,同时保持代码整洁。如无需求,移除装饰器也非常方便。

例如,以下是一个用于记录函数执行耗时的装饰器:

import functools

import time

def log_and_time(func):

  @functools.wraps(func)

  def wrapper(*args, **kwargs):

      func_name = func.__name__

      start_time = time.time()

      result = func(*args, **kwargs)

      end_time = time.time()

      duration = end_time - start_time

      print(f"'{func_name}' completed in {duration:.4f} seconds.\n")

      return result

  return wrapper

假设我们要定义一个生成模拟数据的函数,可以用上面的装饰器:

@log_and_time

def load_simulated_data(n_rows=10000):

  np.random.seed(42)

  df = pd.DataFrame({

      'age': np.random.randint(18, 70, size=n_rows),

      'income': np.random.normal(50000, 15000, size=n_rows),

      'credit_score': np.random.randint(300, 850, size=n_rows),

      'loan_amount': np.random.normal(20000, 5000, size=n_rows),

      'defaulted': np.random.binomial(1, 0.2, size=n_rows)

  })

  for col in ['income', 'credit_score']:

      df.loc[df.sample(frac=0.05).index, col] = np.nan

  return df

执行该函数:

df_loaded = load_simulated_data()

你会看到类似如下的输出结果:

'load_simulated_data' completed in 0.0707 seconds.

装饰器能够正确获取函数名称,并精确给出执行时间。

对于需要封装或统计信息的任务,建议采用装饰器模式。

总结

从初级到中级数据科学家,意味着你要将 Python 编程能力提升到更高层次,不再局限于入门级别。你需要用更有条理和更高效的方式管理数据工作流。在本文中,我们介绍了几种能够助你进阶的 Python 编程模式,包括数据流水线模式、工厂模式和装饰器模式。

希望本文能对你有所帮助!

  • 发表于:
  • 原文链接https://page.om.qq.com/page/O1X3hJ5uTHf5Hs8iFa4_2LfQ0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券