2017-07-17 2 views
2

Ich habe ein Datenrahmen wie diesePython Grundstück gefiltert groupby

df = pd.DataFrame({ 
'comments': {0: 0, 1: 1, 2: 47, 3: 102, 4: 230}, 
'content_len': {0: 4305, 1: 7344, 2: 8431, 3: 5662, 4: 3706}, 
'day': {0: 1, 1: 1, 2: 1, 3: 2, 4: 2}, 
'dayofweek': {0: 2, 1: 2, 2: 2, 3: 3, 4: 3}, 
'domain': {0: 'habrahabr.ru', 
    1: 'habrahabr.ru', 
    2: 'habrahabr.ru', 
    3: 'habrahabr.ru', 
    4: 'geektimes.ru'}, 
'favs': {0: 0, 1: 1, 2: 72, 3: 36, 4: 6}, 
'post_id': {0: 18284, 1: 18285, 2: 18286, 3: 18291, 4: 18294}, 
'views': {0: 236, 1: 353, 2: 1200, 3: 5700, 4: 1400}, 
'votes_minus': {0: 0.0, 1: 0.0, 2: 5.0, 3: 3.0, 4: 15.0}, 
'votes_plus': {0: 0.0, 1: 1.0, 2: 45.0, 3: 72.0, 4: 73.0}, 
'year_month': {0: datetime.strptime('2008-01-01', '%Y-%m-%d'), 
    1: datetime.strptime('2008-01-01', '%Y-%m-%d'), 
    2: datetime.strptime('2008-02-01', '%Y-%m-%d'), 
    3: datetime.strptime('2008-02-01', '%Y-%m-%d'), 
    4: datetime.strptime('2008-03-01', '%Y-%m-%d'),}}) 

Jetzt habe ich verschiedene Grafiken gruppiert nach ‚year_month‘, eine Grafik pro Domain darstellen möchten.

Zum Beispiel Anzahl der Artikel

df[df.domain=='habrahabr.ru'].groupby('year_month').count()[['domain']].rename(columns={'domain':'habrahabr.ru'}).join(
df[df.domain=='geektimes.ru'].groupby('year_month').count()[['domain']].rename(columns={'domain':'geektimes.ru'})).plot() 

oder mittlere content_len

df[df.domain == 'habrahabr.ru'].groupby('year_month').mean()[['content_len']].rename(columns={'content_len':'habrahabr.ru'}).astype(int).join(
df[df.domain == 'geektimes.ru'].groupby('year_month').mean()[['content_len']].rename(columns={'content_len':'geektimes.ru'}).astype(int)).plot() 

Gibt es eine elegantere Lösung als die, die ich gegeben habe?

Antwort

2

Lösungen für alle Domains:

Ich glaube, Sie neue Spalte in groupby Funktion hinzufügen und neu zu gestalten dann durch unstack:

What is the difference between size and count in pandas?

a = df.groupby(['year_month', 'domain']).size().unstack(fill_value=0) 
print (a) 
domain  geektimes.ru habrahabr.ru 
year_month        
2008-01-01    0    2 
2008-02-01    0    2 
2008-03-01    1    0 

a.plot() 

Auch ist möglich, Aggregat von sum, mean ...

b = df.groupby(['year_month', 'domain'])['content_len'].mean().unstack(fill_value=0) 
print (b) 
domain  geektimes.ru habrahabr.ru 
year_month        
2008-01-01   0.0  5824.5 
2008-02-01   0.0  7046.5 
2008-03-01  3706.0   0.0 

b.plot() 

Ein weiteres etwas slowier Lösung ist pivot_table:

a = df.pivot_table(index='year_month', columns='domain', aggfunc='size', fill_value=0) 
print (a) 
domain  geektimes.ru habrahabr.ru 
year_month        
2008-01-01    0    2 
2008-02-01    0    2 
2008-03-01    1    0 


b = df.pivot_table(index='year_month', 
        columns='domain', 
        values='content_len', 
        aggfunc='mean', 
        fill_value=0) 
print (b) 
domain  geektimes.ru habrahabr.ru 
year_month        
2008-01-01    0  5824.5 
2008-02-01    0  7046.5 
2008-03-01   3706   0.0 

Lösungen für die gefilterten Domains:

Wenn nur Notwendigkeit Filter einige Domänen boolean indexing mit isin für Boolen Maske verwenden oder query:

df1 = df[df['domain'].isin(['habrahabr.ru','geektimes.ru'])] 
a = df1.groupby(['year_month', 'domain']).size().unstack(fill_value=0) 
print (a) 
domain  geektimes.ru habrahabr.ru 
year_month        
2008-01-01    0    2 
2008-02-01    0    2 
2008-03-01    1    0 

df1 = df.query('domain == ["habrahabr.ru", "geektimes.ru"]') 
a = df1.groupby(['year_month', 'domain']).size().unstack(fill_value=0) 
print (a) 
domain  geektimes.ru habrahabr.ru 
year_month        
2008-01-01    0    2 
2008-02-01    0    2 
2008-03-01    1    0 
+0

Vielen Dank für die ausführliche Antwort –

+0

Und danke für nette Frage mit netten Proben! Viel Glück! – jezrael