2016-04-02 19 views
1

Vielleicht ist es nur ich, aber ich habe immer str unbefriedigend gefunden. Es ist häufig zu ausführlich, aber nicht oft informativ.Alternative zu `str()` in R

ich wirklich tatsächlich wie die Beschreibung der Funktion (?str):

Kompakt

die interne Struktur eines R-Objekt anzuzeigen

und dieses Bit in bestimmten

Idealer , nur eine Zeile für jede 'Grundstruktur' wird angezeigt.

Nur das, in vielen Fällen, die Standard-Implementierung str wird einer solchen Beschreibung einfach nicht gerecht.

Ok, sagen wir, es funktioniert teilweise gut für data.frame s.

library(ggplot2) 
str(mpg) 

> str(mpg) 
Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 234 obs. of 11 variables: 
$ manufacturer: chr "audi" "audi" "audi" "audi" ... 
$ model  : chr "a4" "a4" "a4" "a4" ... 
$ displ  : num 1.8 1.8 2 2 2.8 2.8 3.1 1.8 1.8 2 ... 
$ year  : int 1999 1999 2008 2008 1999 1999 2008 1999 1999 2008 ... 
$ cyl   : int 4 4 4 4 6 6 6 4 4 4 ... 
$ trans  : chr "auto(l5)" "manual(m5)" "manual(m6)" "auto(av)" ... 
$ drv   : chr "f" "f" "f" "f" ... 
$ cty   : int 18 21 20 21 16 18 18 18 16 20 ... 
$ hwy   : int 29 29 31 30 26 26 27 26 25 28 ... 
$ fl   : chr "p" "p" "p" "p" ... 
$ class  : chr "compact" "compact" "compact" "compact" ... 

Doch für eine data.frame ist es nicht so informativ wie ich möchte. Zusätzlich zur Klasse wäre es sehr nützlich, dass sie beispielsweise die Anzahl von NA-Werten und die Anzahl von eindeutigen Werten zeigt.

Aber für andere Objekte wird es schnell unhandlich. Zum Beispiel:

gp <- ggplot(mpg, aes(x = displ, y = hwy)) + 
    geom_point() 
str(gp) 

> str(gp) 
List of 9 
$ data  :Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 234 obs. of 11 variables: 
    ..$ manufacturer: chr [1:234] "audi" "audi" "audi" "audi" ... 
    ..$ model  : chr [1:234] "a4" "a4" "a4" "a4" ... 
    ..$ displ  : num [1:234] 1.8 1.8 2 2 2.8 2.8 3.1 1.8 1.8 2 ... 
    ..$ year  : int [1:234] 1999 1999 2008 2008 1999 1999 2008 1999 1999 2008 ... 
    ..$ cyl   : int [1:234] 4 4 4 4 6 6 6 4 4 4 ... 
    ..$ trans  : chr [1:234] "auto(l5)" "manual(m5)" "manual(m6)" "auto(av)" ... 
    ..$ drv   : chr [1:234] "f" "f" "f" "f" ... 
    ..$ cty   : int [1:234] 18 21 20 21 16 18 18 18 16 20 ... 
    ..$ hwy   : int [1:234] 29 29 31 30 26 26 27 26 25 28 ... 
    ..$ fl   : chr [1:234] "p" "p" "p" "p" ... 
    ..$ class  : chr [1:234] "compact" "compact" "compact" "compact" ... 
$ layers  :List of 1 
    ..$ :Classes 'LayerInstance', 'Layer', 'ggproto' <ggproto object: Class LayerInstance, Layer> 
    aes_params: list 
    compute_aesthetics: function 
    compute_geom_1: function 
    compute_geom_2: function 
    compute_position: function 
    compute_statistic: function 
    data: waiver 
    draw_geom: function 
    geom: <ggproto object: Class GeomPoint, Geom> 
     aesthetics: function 
     default_aes: uneval 
     draw_group: function 
     draw_key: function 
     draw_layer: function 
     draw_panel: function 
     extra_params: na.rm 
     handle_na: function 
     non_missing_aes: size shape 
     parameters: function 
     required_aes: x y 
     setup_data: function 
     use_defaults: function 
     super: <ggproto object: Class Geom> 
    geom_params: list 
    inherit.aes: TRUE 
    layer_data: function 
    map_statistic: function 
    mapping: NULL 
    position: <ggproto object: Class PositionIdentity, Position> 
     compute_layer: function 
     compute_panel: function 
     required_aes: 
     setup_data: function 
     setup_params: function 
     super: <ggproto object: Class Position> 
    print: function 
    show.legend: NA 
    stat: <ggproto object: Class StatIdentity, Stat> 
     compute_group: function 
     compute_layer: function 
     compute_panel: function 
     default_aes: uneval 
     extra_params: na.rm 
     non_missing_aes: 
     parameters: function 
     required_aes: 
     retransform: TRUE 
     setup_data: function 
     setup_params: function 
     super: <ggproto object: Class Stat> 
    stat_params: list 
    subset: NULL 
    super: <ggproto object: Class Layer> 
$ scales  :Classes 'ScalesList', 'ggproto' <ggproto object: Class ScalesList> 
    add: function 
    clone: function 
    find: function 
    get_scales: function 
    has_scale: function 
    input: function 
    n: function 
    non_position_scales: function 
    scales: list 
    super: <ggproto object: Class ScalesList> 
$ mapping :List of 2 
    ..$ x: symbol displ 
    ..$ y: symbol hwy 
$ theme  : list() 
$ coordinates:Classes 'CoordCartesian', 'Coord', 'ggproto' <ggproto object: Class CoordCartesian, Coord> 
    aspect: function 
    distance: function 
    expand: TRUE 
    is_linear: function 
    labels: function 
    limits: list 
    range: function 
    render_axis_h: function 
    render_axis_v: function 
    render_bg: function 
    render_fg: function 
    train: function 
    transform: function 
    super: <ggproto object: Class CoordCartesian, Coord> 
$ facet  :List of 1 
    ..$ shrink: logi TRUE 
    ..- attr(*, "class")= chr [1:2] "null" "facet" 
$ plot_env :<environment: R_GlobalEnv> 
$ labels  :List of 2 
    ..$ x: chr "displ" 
    ..$ y: chr "hwy" 
- attr(*, "class")= chr [1:2] "gg" "ggplot" 

Whaaattttt ???, was mit "Compact Display" passiert ist. Das ist nicht kompakt!

Und es kann schlimmer sein, verrückt unheimlich, zum Beispiel für S4-Objekte. Wenn Sie das versuchen möchten:

Ich poste die Ausgabe hier nicht, weil es zu viel ist. Es passt nicht einmal in den Konsolenpuffer!

Wie können Sie möglicherweise die interne Struktur des Objekts mit einem solchen nicht-kompakten Display verstehen? Es sind einfach zu viele Details und du verlierst leicht. Oder zumindest tue ich es.

Nun, alles in Ordnung. Bevor mir jemand sagt, hey Kasse ?str und zwinge die Argumente, das ist was ich getan habe. Natürlich kann es besser werden, aber ich bin immer noch etwas enttäuscht von str.

Die beste Lösung, die ich habe ist, eine Funktion zu erstellen, die diese Dies zeigt kompakt die Top-Level-Strukturen des Objekts

if(isS4(obj)){ 
    str(obj, max.level = 2, give.attr = FALSE, give.head = FALSE) 
} else { 
    str(obj, max.level = 1, give.attr = FALSE, give.head = FALSE) 
} 

tun. Der Ausgang für die sp Objekt oben (S4-Objekt) wird viel aufschlussreiche

Formal class 'SpatialPolygonsDataFrame' [package "sp"] with 5 slots 
    [email protected] data  :'data.frame': 243 obs. of 49 variables: 
    [email protected] polygons :List of 243 
    .. .. [list output truncated] 
    [email protected] plotOrder :7 135 28 167 31 23 9 66 84 5 ... 
    [email protected] bbox  :-180 -90 180 83.6 
    [email protected] proj4string:Formal class 'CRS' [package "sp"] with 1 slot 

So, jetzt können Sie 5 Top-Level-Strukturen zu sehen sind, und Sie können sie individuell weiter untersuchen.

Ähnliche für die ggplot Objekt oben, jetzt können Sie

List of 9 
$ data  :Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 234 obs. of 11 variables: 
$ layers  :List of 1 
$ scales  :Classes 'ScalesList', 'ggproto' 
$ mapping :List of 2 
$ theme  : list() 
$ coordinates:Classes 'CoordCartesian', 'Coord', 'ggproto' 
$ facet  :List of 1 
$ plot_env : 
$ labels  :List of 2 

sehen zwar viel besser ist, ich fühle es noch viel mehr interessante sein könnte. Also, vielleicht hat jemand den gleichen Weg gefühlt und eine nette Funktion geschaffen, die informativer ist und dennoch die Informationen kompakt darstellt. Jemand?

+5

Ich denke, das Problem ist, dass R es so leicht macht, eine neue Struktur (S3, S4, R6, Proto, benutzerdefinierte Klasse, etc.) mit beliebigen Ebenen der Verschachtelungsgrad zu definieren, ist es schwer, einen Standard zu machen ' str, das für alle Fälle gut funktioniert, besonders wenn viele spezielle Klassen sich nicht darum kümmern, ein nützliches 'str' zu definieren. Es steht Ihnen jedoch frei, bessere Methoden neu zu definieren, und da es sich um eine Nebeneffekt-Funktion handelt, ist es unwahrscheinlich, dass Sie etwas anderes als Anzeigen unterbrechen. Ich sah ein Problem (Bug) mit gtable, und so definiert ['str.gtable' nach meinem Geschmack] (https://github.com/baptiste/gridextra/blob/master/R/gtable.r#L12). – baptiste

+7

Eine andere Sache, die man beachten sollte, ist der flüchtige Blick() von dplyr. – joran

+0

Wenn ich den Inhalt eines Modellobjekts sehen möchte, benutze ich 'names' und ich betrachte die Hilfeseite sowohl für die Modellfunktion als auch für die zugehörige Zusammenfassungsfunktion. Ich nehme an, Sie könnten eine Art von klassenbasiertem Dispatch-Mechanismus erstellen, wenn ich 'Hmisc :: describe (obj)' Ergebnisse für Datenrahmen, die meine Lieblings-Statistik, aber 'Namen (obj)' für die komplizierteren Listen geben. –

Antwort

1

In einer solchen Situation verwende ich einen Blick aus dem tibble-Paket, das weniger ausführlich und kurz beschreibend für die Datenstruktur ist.

library(tibble) 
glimpse(gp)