2016-10-21 5 views
-1

Ich habe zwei Datenrahmen, die ich basierend auf einem numerischen Wert zusammenführen möchte, aber ich habe Probleme mit der Gleitkommagenauigkeit. Nehmen Sie die beiden data.frames unten als Beispiel:Zusammenführen mit all.equal

> df1 <- data.frame(number = 0.1 + seq(0.01,0.1,0.01), letters = letters[1:10]) 
> df2 <- data.frame(number = seq(0.11,0.2,0.01), LETTERS = LETTERS[1:10]) 
> (merged <- merge(df1, df2, by = "number", all = TRUE)) 
    number letters LETTERS 
1 0.11  a  A 
2 0.12 <NA>  B 
3 0.12  b <NA> 
4 0.13  c  C 
5 0.14  d  D 
6 0.15 <NA>  E 
7 0.15  e <NA> 
8 0.16  f  F 
9 0.17  g  G 
10 0.18  h  H 
11 0.19  i  I 
12 0.20  j  J 

Einige der Werte (0,12 und 0,15) passen bis nicht aufgrund Gleitkommagenauigkeit Fragen wie discussed in this post. Die Lösung für das Finden der Gleichheit dort war die Verwendung der all.equal Funktion, um Fließkommaartefakte zu entfernen, jedoch glaube ich nicht, dass es einen Weg gibt, dies innerhalb der merge Funktion zu tun. Im Moment bin ich dabei, indem ich eine der number Spalten zu einem Zeichen zwinge und sie nach der Zusammenführung wieder auf eine Zahl zurückstelle, aber das ist ein wenig klobig.

> df1c <- df1 
> df1c[["number"]] <- as.character(df1c[["number"]]) 
> merged2 <- merge(df1c, df2, by = "number", all = TRUE) 
> merged2[["number"]] <- as.numeric(merged2[["number"]]) 
> merged2 
    number letters LETTERS 
1 0.11  a  A 
2 0.12  b  B 
3 0.13  c  C 
4 0.14  d  D 
5 0.15  e  E 
6 0.16  f  F 
7 0.17  g  G 
8 0.18  h  H 
9 0.19  i  I 
10 0.20  j  J 

Hat jemand eine bessere Lösung für dieses Problem?

Danke!

EDIT: Ein wenig mehr über die Daten

Ich wollte meine Frage allgemein halten, um es auf andere Probleme der Menschen, aber es scheint, ich muss möglicherweise präziser sein, um eine Antwort zu bekommen.

Es ist wahrscheinlich, dass alle Probleme mit der Verschmelzung mit Gleitkomma-Ungenauigkeit verbunden sind, aber es kann ein wenig schwierig sein, sicher zu sein. Die Daten werden als eine Reihe von Zeitreihenwerten, einer Startzeit und einer Frequenz geliefert. Diese werden dann in ein Objekt der Zeitreihe (ts) umgewandelt, und eine Reihe von Funktionen wird aufgerufen, um Merkmale aus der Zeitreihe zu extrahieren (von denen einer der Wert time ist), der als ein Datenrahmen zurückgegeben wird. Inzwischen wird ein weiterer Satz von Funktionen aufgerufen, um andere Merkmale aus der Zeitreihe als Ziele zu erhalten. Es gibt auch möglicherweise andere Serien, die Eigenschaften erzeugen, die die ursprüngliche Reihe ergänzen. Diese Werte müssen dann mit dem Wert time wiedervereinigt werden.

Jeder dieser Prozesse (Merkmalsextraktion, Zielberechnung, Zusammenführung) muss unabhängig voneinander stattfinden und in einem CSV-Format gespeichert sein, damit er an andere Plattformen weitergegeben werden kann. Speichern als POSIXct Wert wäre schwierig, da die Serie nicht unbedingt in Kalenderzeiten gespeichert werden.

+1

Deshalb verwenden Sie nie einen Wert als Schlüssel ... sehen, wenn Sie Ihren Workflow ändern können ... aber haben Sie in der Zwischenzeit versucht, die Join-Familie von dplyr zu verwenden? zum Beispiel, 'dplyr :: full_join (df1c, df2, by =" number ")' oder irgendein solcher –

+0

Die Zahlenwerte, die ich zusammenführe, kommen von den 'Zeit'-Werten einer Zeitreihe und wandeln diese in ein Zeichen oder einen Faktor um eine Zahl hat ihre eigenen Schwierigkeiten. Auch 'dplyr :: full_join()' funktioniert nicht. Du hast es mit 'df1c' ausgeführt, wo ich' number' in ein Zeichen und nicht in 'df1' umgewandelt habe. – Barker

+0

Warum nicht direkt auf das Datum/Uhrzeit-Feld ohne Konvertierung in numerische verbinden? –

Antwort

0

Rund um die Präzision, die die Zahl gleich sein wird.

> df1$number=round(df1$number,2) 
> df2$number=round(df2$number,2) 
> 
> (merged <- merge(df1, df2, by = "number", all = TRUE)) 
    number letters LETTERS 
1 0.11  a  A 
2 0.12  b  B 
3 0.13  c  C 
4 0.14  d  D 
5 0.15  e  E 
6 0.16  f  F 
7 0.17  g  G 
8 0.18  h  H 
9 0.19  i  I 
10 0.20  j  J 

Wenn Sie das Niveau der Präzision wählen müssen programmatisch dann sollten Sie uns sagen, mehr über die Daten und ob wir vielleicht davon ausgehen, dass es immer aufgrund Gleitkomma-Ungenauigkeit. Wenn ja, sollte eine Rundung auf 10 Dezimalstellen in Ordnung sein. Die all.equal-Funktion verwendet sqrt (.Machine $ double.eps), was in der Regel ähnlich sein sollte wie round(..., 16).

+0

Ich habe oben weitere Informationen hinzugefügt. Vielen Dank. – Barker

Verwandte Themen