Variablen verschachtelt indexieren (autom. Distanzberechnung für mehrere DS)

Wie erweitere ich R um eigene Funktionen oder Pakete? Welches Paket ist passend für meine Fragestellung?

Moderatoren: EDi, jogo

Antworten
sblatt
Beiträge: 5
Registriert: Mo Sep 24, 2018 11:09 am

Variablen verschachtelt indexieren (autom. Distanzberechnung für mehrere DS)

Beitrag von sblatt »

Hallo zusammen,

zu Trainingszwecken habe ich 5 Einträge der "Species-Spalte" des Iris DS gelöscht und möchte diese nun über die Ähnlichkeit der restlichen DS mit Hilfe des Minimums des Euklid'schen Abstands prognostizieren. Für eine Zeile klappt das noch (wenn auch etwas holprig):

Code: Alles auswählen

#Löschung von "Species" in der 1. Zeile von Iris:
zu.bestimmender.Fall <- iris[1,-5]
#Funktion dist() funktioniert nicht: nur die ersten 6 Zeilen werden bestimmt - warum?

#Daher Bestimmung der Distanz (Euklid) zw. Z1 und allen anderen DS
#Als Zielklasse des zu bestimmenden 1. DS wird die Ausprägung der ZK des DS mit 
#der geringsten Distanz übernommen
#dist_1 <- 0
#i <- 2
for (i in 2:150){
  dist_1[i] <- sqrt((iris[i,1]-iris[1,1])^2+(iris[i,2]-iris[1,2])^2+(iris[i,3]-iris[1,3])^2+(iris[i,4]-iris[1,4])^2)
}

Zielklasse.gesucht <- iris[which(dist_1[-1]==min(dist_1[-1]))+1,5]  
#+1 ist Korrektur für die falsch zählende Schleife, -1 eliminiert den 1. DS (0), damit das echte Min gefunden wird

#Das war ein Bsp. für einen zu bestimmenden Datensatz - gibt es mehrere DS, bei 
#denen das Attribut fehlt, muss diese Prozedur über eine weitere Schleife auf alle
#betroffenen DS ausgedehnt werden - wie? -> die auf Z1 zeigende 1 muss ebenfalls
#indexiert werden mit den Nummern aller Zeilen, bei denen ebenfalls Attribut leer

#Iris-Datensatz wurde modifiziert: 5 Einträge bei Species wurden gelöscht mit der
#Zielsetzung, diese alle automatisiert über eine verschachtelte Schleife über
#Dist_Euklid zu ermitteln

# 1. Ermittlung der betroffenen DS
iris.fehlend <- subset(iris.5fehlend, iris.5fehlend$species=='')
iris.gefuellt <- subset(iris.5fehlend, iris.5fehlend$species!='')

for (n in 1:nrow(iris.fehlend)) {
  for (i in 1:nrow(iris.gefuellt)) {
dist[n, i] <- sqrt((iris.gefuellt[i,1]-iris.fehlend[n,1])^2+(iris.gefuellt[i,2]-iris.fehlend[n,2])^2+(iris.gefuellt[i,3]-iris.fehlend[n,3])^2+(iris.gefuellt[i,4]-iris.fehlend[n,4])^2)

}
} 
Dies führt zu folgender Fehlermeldung:
Error in dist[n, i] <- sqrt((iris.gefuellt[i, 1] - iris.fehlend[n, 1])^2 + :
object of type 'closure' is not subsettable


Mein Ziel ist eigentlich, dass mir mein Code am Ende das Attribut "Species" für die 5 Zeilen, wo dieser Eintrag fehlt, automatisch ausspuckt, indem eine Schleife 5 mal (für jede Zeile, wo Attribut fehlt) den ähnlichsten DS ermittelt, daraus das "Species" übernimmt und diesen Wert dann in die Zelle reinschreibt, wo er fehlt. Das mit der mehrfachen Indexierung scheint aber zumindet so nicht zu funktionieren. Wie kann ich denn eine Variable so dynamisieren, dass ich den Code nicht für jede einzelne Fehlerzeile schreiben muss?


Vielen Dank schon mal
bigben
Beiträge: 2771
Registriert: Mi Okt 12, 2016 9:09 am

Re: Variablen verschachtelt indexieren (autom. Distanzberechnung für mehrere DS)

Beitrag von bigben »

R sieht diesen Zeilenanfang:

Code: Alles auswählen

dist[n, i] <-
und überlegt, was Du mit 'dist' meinen könntest. Eine Variable mit Namen 'dist' existiert nicht, wohl aber eine Funktion mit Namen 'dist'. Als nächstes sieht R, dass Du mit der eckigen Klammer ein subset von dist auswählen möchtest. Funktionen aber aber keine subsets, deshalb der Fehler, den Du auch so reproduzieren kannst:

Code: Alles auswählen

dist[1]
#wahlweise auch
plot[1]
Die Fehlermeldung ist also ein berechtigter Syntax error.

LG,
Bernhard
---
Programmiere stets so, dass die Maxime Deines Programmierstils Grundlage allgemeiner Gesetzgebung sein könnte
jogo
Beiträge: 2085
Registriert: Fr Okt 07, 2016 8:25 am

Re: Variablen verschachtelt indexieren (autom. Distanzberechnung für mehrere DS)

Beitrag von jogo »

Hallo sblatt,

bei mir sieht das so aus:

Code: Alles auswählen

iris1 <- iris[1, ]
i1 <- unlist(iris1[-5])

irisRest <- iris[-1,]
M <- as.matrix(irisRest[-5])

rowSums((sweep(M, 2, i1))^2) ## das ist der Vektor dist
min(rowSums((sweep(M, 2, i1))^2))
w <- which.min(rowSums((sweep(M, 2, i1))^2))
sum((unlist(irisRest[w, -5]) - i1)^2) ## Kontrolle

irisRest$Species[w] ## welche Spezies?
iris[1, 5] ## Vergleich
Oder man verwendet die Funktion dist()

Code: Alles auswählen

d <- as.matrix(dist(iris[-5]))[1,]
d
Für fünf verschiedene Zeilen des Datensatzes sieht die Vorhersage bei mir so aus:

Code: Alles auswählen

set.seed(42)
s <- sample(1:150, 5)
irisS <- iris[s, ]
irisRest <- iris[-s, ]
M <- as.matrix(irisRest[-5])

findeSpez <- function(i1) {
  w <- which.min(rowSums((sweep(M, 2, i1))^2))
  irisRest$Species[w] ## welche Spezies?
}
data.frame(predSpez=apply(irisS[-5], 1, findeSpez), echt=irisS$Species)
Gruß, Jörg
sblatt
Beiträge: 5
Registriert: Mo Sep 24, 2018 11:09 am

Re: Variablen verschachtelt indexieren (autom. Distanzberechnung für mehrere DS)

Beitrag von sblatt »

Vielen Dank, schau ich mir in Ruhe an, bin leider noch immer irgendwie Anfänger.
Athomas
Beiträge: 768
Registriert: Mo Feb 26, 2018 8:19 pm

Re: Variablen verschachtelt indexieren (autom. Distanzberechnung für mehrere DS)

Beitrag von Athomas »

bin leider noch immer irgendwie Anfänger
Kein Problem, das waren wir alle mal :D !

Aber wenn Du R über einen längeren Zeitraum und/oder intensiver nutzen möchtest, solltest Du an diesem Zustand etwas ändern!
Das ist für alle Beteiligten besser...
Benutzeravatar
EDi
Beiträge: 1599
Registriert: Sa Okt 08, 2016 3:39 pm

Re: Variablen verschachtelt indexieren (autom. Distanzberechnung für mehrere DS)

Beitrag von EDi »

Code: Alles auswählen

object of type 'closure' is not subsettable
Die Fehlermeldung ist also ein berechtigter Syntax error.
Und hier und hier die Erklärung warum Funktionen "closures" sind (und in R so bezeichnet werden).

Code: Alles auswählen

> typeof(dist)
[1] "closure"
Siehe auch ?typeof. Als Fehlemeldung wäre es vermutlich besser "function", statt "closure" zu nehmen....
Bitte immer ein reproduzierbares Minimalbeispiel angeben. Meinungen gehören mir und geben nicht die meines Brötchengebers wieder.

Dieser Beitrag ist lizensiert unter einer CC BY 4.0 Lizenz
Bild.
jogo
Beiträge: 2085
Registriert: Fr Okt 07, 2016 8:25 am

Re: Variablen verschachtelt indexieren (autom. Distanzberechnung für mehrere DS)

Beitrag von jogo »

Hallo Sven,

sblatt schrieb:
Hallo Jörg,

vielen Dank für deine Hilfe. Ich hätte nicht gedacht, dass man dies so elegant lösen kann. Ich zerbreche mir allerdings schon seit Tagen den Kopf, was genau in dieser Zeile passiert:

w <- which.min(rowSums((sweep(M, 2, i1))^2))

Was ich verstehe ist, dass die Zeile gesucht wird, bei der die Zeilensumme ihr Minimum hat. Bei sweep verstehe ich noch, dass eine Funktion i1 spaltenweise auf die Matrix M angewendet wird und dies dann noch quadriert wird. Was ist denn aber die Funktion i1? Ist das eine definierte statistische Funktion für die Abstandermittlung? Ich kriege die Formel der Abstandermittlung nach Euklid einfach nicht überein mit deiner Formel - oder liegt dem ein vereinfachender mathematischer Schluss zugrunde?

Wäre dir dankbar, wenn du hier noch etwas Licht ins Dunkle bringen könntest.
Das Objekt i1 habe ich doch in meinem Code definiert:

Code: Alles auswählen

iris1 <- iris[1, ]
i1 <- unlist(iris1[-5])
Es ist die erste Zeile aus dem Dataframe iris ohne "Species".
Der Dokumentation von sleep() ist zu entnehmen, dass das vierte Argument die Funktion ist - und wenn die Funktion nicht angegeben wird, ist es die Subtraktion. Ich hätte beim sleep() also auch schreiben können:

Code: Alles auswählen

sweep(x=M, MARGIN=2, STATS=i1, FUN = "-")
Bitte schaue Dir die Dokumentation von sweep() an:

Code: Alles auswählen

help("sweep")
und auch die Beispiele:

Code: Alles auswählen

example("sweep")
Was insgesamt berechnet wird, ist nicht ganz die euklidische Norm, denn dafür fehlt die Quadratwurzel (über der Summe der Quadrate). Für die gesuchte Minimumstelle ist das aber unerheblich.

Bitte lies im Bereich FAQ den Text viewtopic.php?f=20&t=45 und halte Dich zukünftig daran!

Gruß, Jörg
Antworten