Option 0
numpy
trancher avec pd.factorize
Je vais utiliser pd.factorize
pour produire des valeurs entières pour chaque 'Name'
y 'Mealtime'
. Parallèlement, j'obtiens également les valeurs uniques. Chaque valeur entière finit par correspondre à l'élément qui se trouve à cette position entière dans le tableau des valeurs uniques.
Je connais maintenant le nombre de noms uniques et d'heures de repas uniques, ce qui me permet de connaître la taille de mon éventuel tableau pivoté. Je crée donc un tableau vide qui attendra que des valeurs lui soient attribuées.
Puisque j'ai factorisé et que les facteurs sont des positions entières, je peux les utiliser pour découper mon tableau vide à des fins d'affectation... c'est ce que je fais. Enfin, j'assemble le tout avec un nouveau dataframe brillant.
fn, un = pd.factorize(df.Name.values)
fm, um = pd.factorize(df.Mealtime.values)
v = np.empty((un.size, um.size), dtype=object)
v[fn, fm] = df.Food.values
pd.DataFrame(v, un, um)
8:00 am 1:00 pm 6:00 pm
John cereal salad pasta
Sara yogurt panini steak
Jake coffee burrito salad
Option 1
Utilisation set_index
/ unstack
df.set_index(['Name', 'Mealtime']).Food.unstack()
Mealtime 1:00 pm 6:00 pm 8:00 am
Name
Jake burrito salad coffee
John salad pasta cereal
Sara panini steak yogurt
Option 2
Utilisation defaultdict
from collections import defaultdict
d = defaultdict(dict)
[d[m].setdefault(n, f) for n, m, f in df.values];
pd.DataFrame(d)
1:00 pm 6:00 pm 8:00 am
Jake burrito salad coffee
John salad pasta cereal
Sara panini steak yogurt
Option 3
Force brute
out = pd.DataFrame(index=df.Name.unique(), columns=df.Mealtime.unique())
[out.set_value(n, m, f) for n, m, f in df.values]
out
8:00 am 1:00 pm 6:00 pm
John cereal salad pasta
Sara yogurt panini steak
Jake coffee burrito salad
Calendrier
Conclusion : utiliser pivot
pour des données plus importantes avec pandas pur. Il est difficile de faire mieux que sa simplicité et sa capacité à faire le travail dans ce scénario. Mais si vous voulez pivoter à une vitesse effrénée, essayez Option 0 .
%%timeit
fn, un = pd.factorize(df.Name.values)
fm, um = pd.factorize(df.Mealtime.values)
v = np.empty((un.size, um.size), dtype=object)
v[fn, fm] = df.Food.values
pd.DataFrame(v, un, um)
%timeit df.set_index(['Name', 'Mealtime']).Food.unstack()
%timeit df.pivot('Name', 'Mealtime', 'Food')
%timeit d = defaultdict(dict); [d[m].setdefault(n, f) for n, m, f in df.values]; pd.DataFrame(d)
%timeit out = pd.DataFrame(index=df.Name.unique(), columns=df.Mealtime.unique()); [out.set_value(n, m, f) for n, m, f in df.values]; out
Petites données
1000 loops, best of 3: 300 µs per loop
1000 loops, best of 3: 1.82 ms per loop
1000 loops, best of 3: 1.11 ms per loop
1000 loops, best of 3: 541 µs per loop
1000 loops, best of 3: 656 µs per loop
Données plus importantes
from string import ascii_letters
foods = np.array([
'cereal', 'salad', 'pasta', 'yogurt',
'panini', 'steak', 'coffee', 'burrito'
], dtype=object)
times = pd.date_range(
pd.datetime.now().date(), periods=24, freq='H'
).strftime('%-I:00 %p')
names = list(ascii_letters)
idx = pd.MultiIndex.from_product([names, times], names=['Name', 'Mealtime'])
df = pd.DataFrame(dict(
Food=np.random.choice(foods, idx.size),
), idx).reset_index()
1000 loops, best of 3: 383 µs per loop
1000 loops, best of 3: 1.99 ms per loop
1000 loops, best of 3: 1.34 ms per loop
100 loops, best of 3: 2.78 ms per loop
100 loops, best of 3: 6.6 ms per loop