J'ai ce code:
for index, row in df.iterrows():
for index1, row1 in df1.iterrows():
if df['budget'].iloc[index] == 0:
if df['production_companies'].iloc[index] == df1['production_companies'].iloc[index1]
and df['release_date'].iloc[index].year == df1['release_year'].iloc[index1] :
df['budget'].iloc[index] = df1['mean'].iloc[index1]
Cela fonctionne, mais il faudrait trop de temps pour terminer. Comment puis-je le faire fonctionner plus rapidement? J'ai aussi essayé:
df.where((df['budget'] != 0 and df['production_companies'] != df1['production_companies']
and df['release_date'] != df1['release_year']),
other = pd.replace(to_replace = df['budget'],
value = df1['mean'], inplace = True))
Ça devrait être plus rapide mais ça ne marche pas. Comment puis-je y parvenir? Je vous remercie!
df
ressemble à ceci:
budget; production_companies; release_date ;title
0; Villealfa Filmproduction Oy ;10/21/1988; Ariel
0; Villealfa Filmproduction Oy ;10/16/1986; Shadows in Paradise
4000000; Miramax Films; 12/25/1995; Four Rooms
0; Universal Pictures; 10/15/1993; Judgment Night
42000; inLoops ;1/1/2006; Life in Loops (A Megacities RMX)
...
Et df1
:
production_companies; release_year; mean;
Metro-Goldwyn-Mayer (MGM); 1998; 17500000
Metro-Goldwyn-Mayer (MGM); 1999; 12500000
Metro-Goldwyn-Mayer (MGM); 2000; 12000000
Metro-Goldwyn-Mayer (MGM) ;2001 ;43500000
Metro-Goldwyn-Mayer (MGM); 2002 ;12000000
Metro-Goldwyn-Mayer (MGM) ;2003; 36000000
Metro-Goldwyn-Mayer (MGM); 2004 ;27500000
...
Je veux remplacer la valeur 0 de df
par la valeur "moyenne" de df1
si l'année et la société de production sont les mêmes.
3 réponses
N'utilisez pas de boucles pour cette tâche
Le principal avantage des pandas est la fonctionnalité vectorisée.
Une façon de vectoriser votre calcul consiste à aligner les indices puis à utiliser pd.DataFrame.index.map
. Pour extraire l'année, vous devez d'abord convertir en datetime
.
Données de @ALollz.
# convert release_date to datetime and calculate year
df['release_date'] = pd.to_datetime(df['release_date'])
df['year'] = df['release_date'].dt.year
# create mapping from df1
s = df1.set_index(['production_companies', 'release_year'])['mean']
# use map on selected condition
mask = df['budget'] == 0
df.loc[mask, 'budget'] = df[mask].set_index(['production_company', 'year']).index.map(s.get)
print(df)
# budget production_company release_date title year
# 0 1000000 Villealfa Filmproduction Oy 1988-10-21 AAA 1988
# 1 100 Villealfa Filmproduction Oy 1986-10-18 BBB 1986
# 2 30000000 Villealfa Filmproduction Oy 1955-12-25 CCC 1955
# 3 1000 Miramax Films 2006-01-01 DDD 2006
# 4 5000000 Miramax Films 2017-04-13 EEE 2017
Vous pouvez supprimer rapidement un cycle en utilisant votre instruction if plus tôt:
for index, row in df.iterrows():
if df['budget'].iloc[index] == 0:
for index1, row1 in df1.iterrows():
if df['production_companies'].iloc[index] == df1['production_companies'].iloc[index1] and df['release_date'].iloc[index].year == df1['release_year'].iloc[index1] :
df['budget'].iloc[index] = df1['mean'].iloc[index1]
Débarrassez-vous de toutes les boucles, vous pouvez accomplir cela efficacement avec une fusion. Ici, j'ai fourni quelques exemples de données, car aucune des données que vous avez fournies ne fusionnera réellement. Vous voulez vous assurer que release_date
dans df
est une date / heure, si ce n'est pas déjà fait.
import pandas as pd
import numpy as np
df = pd.DataFrame({'budget': [0, 100, 0, 1000, 0],
'production_company': ['Villealfa Filmproduction Oy', 'Villealfa Filmproduction Oy',
'Villealfa Filmproduction Oy', 'Miramax Films', 'Miramax Films'],
'release_date': ['10/21/1988', '10/18/1986', '12/25/1955', '1/1/2006', '4/13/2017'],
'title': ['AAA', 'BBB', 'CCC', 'DDD', 'EEE']})
df1 = pd.DataFrame({'production_companies': ['Villealfa Filmproduction Oy', 'Villealfa Filmproduction Oy',
'Villealfa Filmproduction Oy', 'Miramax Films', 'Miramax Films'],
'release_year': [1988, 1986, 1955, 2006, 2017],
'mean': [1000000, 2000000, 30000000, 4000000, 5000000]})
df['release_date'] = pd.to_datetime(df.release_date, format='%m/%d/%Y')
# budget production_company release_date title
#0 0 Villealfa Filmproduction Oy 1988-10-21 AAA
#1 100 Villealfa Filmproduction Oy 1986-10-18 BBB
#2 0 Villealfa Filmproduction Oy 1955-12-25 CCC
#3 1000 Miramax Films 2006-01-01 DDD
#4 0 Miramax Films 2017-04-13 EEE
Ensuite, vous souhaitez remplacer le budget où il est 0 par la moyenne si la société de production et l'année correspondent. Donc, comme fusion, c'est:
df.loc[df.budget==0, 'budget'] = (df.merge(df1, left_on=['production_company',
df.release_date.dt.year], right_on=['production_companies', 'release_year'], how='left')
.loc[df.budget==0, 'mean'])
# budget production_company release_date title
#0 1000000 Villealfa Filmproduction Oy 1988-10-21 AAA
#1 100 Villealfa Filmproduction Oy 1986-10-18 BBB
#2 30000000 Villealfa Filmproduction Oy 1955-12-25 CCC
#3 1000 Miramax Films 2006-01-01 DDD
#4 5000000 Miramax Films 2017-04-13 EEE
Si vous ne disposez pas de données mean
pour une société de production et une année données, les 0
dans budget
seront remplacés par np.NaN
, vous pouvez donc les laisser ou remplacez-les à 0 si vous le souhaitez.
Questions connexes
De nouvelles questions
python
Python est un langage de programmation multi-paradigme, typé dynamiquement et polyvalent. Il est conçu pour être rapide à apprendre, comprendre, utiliser et appliquer une syntaxe propre et uniforme. Veuillez noter que Python 2 est officiellement hors support à partir du 01-01-2020. Néanmoins, pour les questions Python spécifiques à la version, ajoutez la balise [python-2.7] ou [python-3.x]. Lorsque vous utilisez une variante Python (par exemple, Jython, PyPy) ou une bibliothèque (par exemple, Pandas et NumPy), veuillez l'inclure dans les balises.