DataFrame offre une API de données structurées pour MaxCompute. Cette rubrique explique comment créer des objets DataFrame et effectuer des opérations courantes sur les données, telles que le filtrage, l'agrégation et les jointures.
Préparation des données
Les exemples utilisent les fichiers u.user, u.item et u.data, qui contiennent respectivement les données relatives aux utilisateurs, aux films et aux notes.
-
Créez les tables :
-
La table
pyodps_ml_100k_userspour les données utilisateur.CREATE TABLE IF NOT EXISTS pyodps_ml_100k_users ( user_id BIGINT COMMENT 'User ID', age BIGINT COMMENT 'Age', sex STRING COMMENT 'Gender', occupation STRING COMMENT 'Occupation', zip_code STRING COMMENT 'Zip code' ); -
La table
pyodps_ml_100k_moviespour les données de film.CREATE TABLE IF NOT EXISTS pyodps_ml_100k_movies ( movie_id BIGINT COMMENT 'Movie ID', title STRING COMMENT 'Movie title', release_date STRING COMMENT 'Release date', video_release_date STRING COMMENT 'Video release date', IMDb_URL STRING COMMENT 'IMDb URL', unknown TINYINT COMMENT 'Unknown', Action TINYINT COMMENT 'Action', Adventure TINYINT COMMENT 'Adventure', Animation TINYINT COMMENT 'Animation', Children TINYINT COMMENT 'Children', Comedy TINYINT COMMENT 'Comedy', Crime TINYINT COMMENT 'Crime', Documentary TINYINT COMMENT 'Documentary', Drama TINYINT COMMENT 'Drama', Fantasy TINYINT COMMENT 'Fantasy', FilmNoir TINYINT COMMENT 'Film Noir', Horror TINYINT COMMENT 'Horror', Musical TINYINT COMMENT 'Musical', Mystery TINYINT COMMENT 'Mystery', Romance TINYINT COMMENT 'Romance', SciFi TINYINT COMMENT 'Sci-Fi', Thriller TINYINT COMMENT 'Thriller', War TINYINT COMMENT 'War', Western TINYINT COMMENT 'Western' ); -
La table
pyodps_ml_100k_ratingspour les données de notation.CREATE TABLE IF NOT EXISTS pyodps_ml_100k_ratings ( user_id BIGINT COMMENT 'User ID', movie_id BIGINT COMMENT 'Movie ID', rating BIGINT COMMENT 'Rating', timestamp BIGINT COMMENT 'Timestamp' )
-
-
Utilisez la commande Tunnel Upload pour importer les fichiers de données locaux dans les tables MaxCompute. Pour plus d'informations sur les commandes Tunnel, consultez la section Tunnel Commands.
Tunnel upload -fd | path_to_file/u.user pyodps_ml_100k_users; Tunnel upload -fd | path_to_file/u.item pyodps_ml_100k_movies; Tunnel upload -fd | path_to_file/u.data pyodps_ml_100k_ratings;
Opérations DataFrame
Une fois les trois tables prêtes — pyodps_ml_100k_movies, pyodps_ml_100k_users et pyodps_ml_100k_ratings — vous pouvez explorer les opérations DataFrame dans IPython.
IPython nécessite Python. Exécutez pip install IPython pour l'installer, puis lancez ipython pour démarrer l'environnement interactif.
-
Créez un objet ODPS.
import os from odps import ODPS # Make sure that the ALIBABA_CLOUD_ACCESS_KEY_ID environment variable is set to your Access Key ID, # and the ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variable is set to your Access Key Secret. # We recommend that you avoid hardcoding the Access Key ID and Access Key Secret in your code. o = ODPS( os.getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'), os.getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET'), project='your-default-project', endpoint='your-end-point', ) -
Créez un objet DataFrame à partir d'une table.
from odps.df import DataFrame users = DataFrame(o.get_table('pyodps_ml_100k_users')); -
Affichez les noms des colonnes et les types de données avec la propriété
dtypes.print(users.dtypes)Résultat :
odps.Schema { user_id int64 age int64 sex string occupation string zip_code string } -
Affichez un aperçu des N premières lignes avec la méthode
head.print(users.head(10))Résultat :
user_id age sex occupation zip_code 0 1 24 M technician 85711 1 2 53 F other 94043 2 3 23 M writer 32067 3 4 24 M technician 43537 4 5 33 F other 15213 5 6 42 M executive 98101 6 7 57 M administrator 91344 7 8 36 M administrator 05201 8 9 29 M student 01002 9 10 53 M lawyer 90703 -
Pour travailler avec des colonnes spécifiques, utilisez l'une des méthodes suivantes :
-
Sélectionnez un sous-ensemble de colonnes.
print(users[['user_id', 'age']].head(5))Résultat :
user_id age 0 1 24 1 2 53 2 3 23 3 4 24 4 5 33 -
Excluez des colonnes spécifiques.
print(users.exclude('zip_code', 'age').head(5))Résultat :
user_id sex occupation 0 1 M technician 1 2 F other 2 3 M writer 3 4 M technician 4 5 F other -
Excluez des colonnes et ajoutez des colonnes calculées. Par exemple, créez une colonne booléenne nommée
sex_booldont la valeur est True sisexestM, et False sinon.print(users.select(users.exclude('zip_code', 'sex'), sex_bool=users.sex == 'M').head(5))Résultat :
user_id age occupation sex_bool 0 1 24 technician True 1 2 53 other False 2 3 23 writer True 3 4 24 technician True 4 5 33 other False
-
-
Comptez le nombre d'utilisateurs masculins et féminins.
print(users.groupby(users.sex).agg(count=users.count()))Résultat :
sex count 0 F 273 1 M 670 -
Regroupez les utilisateurs par profession, triez-les par ordre décroissant et affichez les 10 professions les plus représentées.
df = users.groupby('occupation').agg(count=users['occupation'].count()) df1 = df.sort(df['count'], ascending=False) print(df1.head(10))Résultat :
occupation count 0 student 196 1 other 105 2 educator 95 3 administrator 79 4 engineer 67 5 programmer 66 6 librarian 51 7 writer 45 8 executive 32 9 scientist 31Vous pouvez également utiliser la méthode
value_countspour une syntaxe plus concise. Le nombre de lignes renvoyées est limité paroptions.df.odps.sort.limit. Pour plus d'informations, consultez la section Configuration.df = users.occupation.value_counts()[:10] print(df.head(10))Résultat :
occupation count 0 student 196 1 other 105 2 educator 95 3 administrator 79 4 engineer 67 5 programmer 66 6 librarian 51 7 writer 45 8 executive 32 9 scientist 31 -
Joignez les trois tables avec
joinet enregistrez le résultat dans une nouvelle table nommée pyodps_ml_100k_lens.movies = DataFrame(o.get_table('pyodps_ml_100k_movies')) ratings = DataFrame(o.get_table('pyodps_ml_100k_ratings')) o.delete_table('pyodps_ml_100k_lens', if_exists=True) lens = movies.join(ratings).join(users).persist('pyodps_ml_100k_lens') print(lens.dtypes)Résultat :
odps.Schema { movie_id int64 title string release_date string ideo_release_date string imdb_url string unknown int64 action int64 adventure int64 animation int64 children int64 comedy int64 crime int64 documentary int64 drama int64 fantasy int64 filmnoir int64 horror int64 musical int64 mystery int64 romance int64 scifi int64 thriller int64 war int64 western int64 user_id int64 rating int64 timestamp int64 age int64 sex string occupation string zip_code string }
Traitement des données DataFrame
Tout d'abord, téléchargez le jeu de données Iris. Les étapes suivantes utilisent un nœud PyODPS dans DataWorks. Pour plus d'informations, consultez la section Develop a PyODPS 3 task.
-
Créez une table de données de test.
Créez une table dans DataWorks :
Dans le volet Business Flow, cliquez avec le bouton droit sur MaxCompute et sélectionnez Create Table. Dans la boîte de dialogue Create Table, spécifiez un Path, saisissez un Name, puis cliquez sur Create pour accéder à l'éditeur de table.
Cliquez sur DDL
dans le coin supérieur gauche de la page d'édition.-
Saisissez l'instruction DDL suivante, puis exécutez-la pour créer la table.
CREATE TABLE pyodps_iris ( sepallength double COMMENT 'sepal length (cm)', sepalwidth double COMMENT 'sepal width (cm)', petallength double COMMENT 'petal length (cm)', petalwidth double COMMENT 'petal width (cm)', name string COMMENT 'name' ) ;
-
Importez les données de test.
-
Cliquez avec le bouton droit sur la nouvelle table, sélectionnez Import Data, puis cliquez sur Next pour importer le jeu de données téléchargé.
Dans la boîte de dialogue Import Data, définissez la méthode d'importation des données sur Upload Local File et le format de fichier sur CSV. Sélectionnez le fichier iris.csv téléchargé. Définissez le délimiteur sur Comma, l'encodage source sur GBK et la ligne de départ sur 1. Sélectionnez Yes pour « First Row Is Header ». Après avoir vérifié que l'aperçu des données est correct, cliquez sur Next.
Cliquez sur Match by Position pour importer les données.
-
Dans le volet Business Flow, cliquez avec le bouton droit sur MaxCompute, sélectionnez Create Node, puis choisissez PyODPS 3 pour créer un nœud PyODPS destiné à stocker et exécuter votre code.
-
Saisissez le code et cliquez sur l'icône d'exécution
. Une fois le code exécuté, vous pouvez consulter les résultats dans l'onglet Run log ci-dessous. Voici le code :from odps import ODPS from odps.df import DataFrame, output import os # Make sure that the ALIBABA_CLOUD_ACCESS_KEY_ID environment variable is set to your Access Key ID, # and the ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variable is set to your Access Key Secret. # We recommend that you avoid hardcoding the Access Key ID and Access Key Secret in your code. o = ODPS( os.getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'), os.getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET'), project='your-default-project', endpoint='your-end-point', ) # Create a DataFrame object named iris from the MaxCompute table. iris = DataFrame(o.get_table('pyodps_iris')) print(iris.head(10)) # Print part of the iris DataFrame. print(iris.sepallength.head(5)) # Use a custom function to calculate the sum of two columns in the iris DataFrame. print(iris.apply(lambda row: row.sepallength + row.sepalwidth, axis=1, reduce=True, types='float').rename('sepaladd').head(3)) # Specify the output names and types for the function. @output(['iris_add', 'iris_sub'], ['float', 'float']) def handle(row): # Use the yield keyword to return multiple output rows. yield row.sepallength - row.sepalwidth, row.sepallength + row.sepalwidth yield row.petallength - row.petalwidth, row.petallength + row.petalwidth # Print the first 5 rows of the result. axis=1 indicates a row-by-row operation. print(iris.apply(handle, axis=1).head(5))Résultats :
# print(iris.head(10)) sepallength sepalwidth petallength petalwidth name 0 4.9 3.0 1.4 0.2 Iris-setosa 1 4.7 3.2 1.3 0.2 Iris-setosa 2 4.6 3.1 1.5 0.2 Iris-setosa 3 5.0 3.6 1.4 0.2 Iris-setosa 4 5.4 3.9 1.7 0.4 Iris-setosa 5 4.6 3.4 1.4 0.3 Iris-setosa 6 5.0 3.4 1.5 0.2 Iris-setosa 7 4.4 2.9 1.4 0.2 Iris-setosa 8 4.9 3.1 1.5 0.1 Iris-setosa 9 5.4 3.7 1.5 0.2 Iris-setosa # print(iris.sepallength.head(5)) sepallength 0 4.9 1 4.7 2 4.6 3 5.0 4 5.4 # print(iris.apply(lambda row: row.sepallength + row.sepalwidth, axis=1, reduce=True, types='float').rename('sepaladd').head(3)) sepaladd 0 7.9 1 7.9 2 7.7 # print(iris.apply(handle,axis=1).head(5)) iris_add iris_sub 0 1.9 7.9 1 1.2 1.6 2 1.5 7.9 3 1.1 1.5 4 1.5 7.7