18/04/2016
Har du nogensinde siddet dybt begravet i din R-kode, klar til at udføre en simpel matematisk operation, kun for at blive mødt af den frustrerende fejlmeddelelse: Error: non-numeric argument to binary operator? Du er ikke alene. Denne fejl er en af de mest almindelige for både nye og erfarne R-brugere, men heldigvis er den også en af de nemmeste at forstå og rette. Fejlen signalerer et fundamentalt problem med datatyper: Du forsøger at udføre en matematisk beregning på noget, som R ikke genkender som et tal.

I denne dybdegående artikel vil vi nedbryde præcis, hvad denne fejl betyder, hvorfor den opstår, og vigtigst af alt, hvordan du kan løse den effektivt. Vi vil gennemgå praktiske eksempler, fra simple additioner til operationer i dataframes, så du bliver fuldt ud rustet til at håndtere denne udfordring og skrive mere robust R-kode fremover.
Hvad er en binær operator, og hvorfor kræver den tal?
For at forstå fejlen skal vi først forstå begrebet 'binær operator'. I programmering er en binær operator simpelthen en operation, der tager to input – eller 'operander' – for at producere et enkelt output. De mest kendte binære operatorer er de aritmetiske, som vi bruger til grundlæggende matematik.
I R inkluderer disse blandt andet:
+: Addition-: Subtraktion*: Multiplikation/: Division^eller**: Eksponentiering (opløftning i potens)%%: Modulus (resten ved division)%/%: Heltalsdivision
Den gyldne regel for disse operatorer er, at de er designet til at arbejde med tal. De ved, hvordan man lægger 5 til 10, men de ved ikke, hvordan man lægger 5 til ordet "ti". Når R støder på en anmodning om at udføre en matematisk operation, hvor en eller begge operander ikke er af en numerisk datatype (som f.eks. numeric eller integer), stopper den processen og returnerer fejlen non-numeric argument to binary operator for at fortælle dig, at noget er galt med de data, du har givet den.
Hovedårsagen til fejlen: Datatyper i konflikt
Kernen i problemet ligger næsten altid i en uoverensstemmelse mellem datatyper. Ofte ser data numeriske ud for det menneskelige øje, men R fortolker dem som tekst (character). Dette sker hyppigt, når data importeres fra filer som CSV, hvor tal kan være omgivet af anførselstegn.

Lad os se på et helt basalt eksempel:
> 5 + '3' Error in 5 + "3": non-numeric argument to binary operator
Her er 5 et tal, men '3' er en karakterstreng (tekst), fordi det er omsluttet af anførselstegn. R kan ikke udføre addition mellem et tal og en tekststreng.
For at diagnosticere dette problem kan vi bruge funktionerne class() og is.numeric():
> class(5) [1] "numeric" > class('3') [1] "character" > is.numeric(5) [1] TRUE > is.numeric('3') [1] FALSE
Disse funktioner bekræfter vores mistanke. Den ene operand er numerisk, den anden er det ikke. Løsningen er at konvertere tekststrengen til et tal. Dette gøres nemt med funktionen as.numeric(), som forsøger at tvinge sit input til at blive en numerisk type.
Her er den korrigerede kode:
> 5 + as.numeric('3') [1] 8
Nu virker det! Vi har eksplicit fortalt R, at den skal behandle '3' som et tal, og beregningen kan udføres uden problemer.
Praktisk eksempel: Analyse af en DataFrame
Denne fejl opstår meget ofte, når man arbejder med rigtige datasæt i en DataFrame. Forestil dig, at vi har en dataframe, der sporer et sportsholds præstationer med antal sejre og tab over 12 måneder.

df <- data.frame( month = 1:12, wins = c('10', '7', '8', '12', '5', '4', '10', '8', '9', '7', '2', '11'), losses = c(2, 5, 9, 1, 9, 10, 2, 4, 2, 3, 8, 3) )
Bemærk, at wins-kolonnen blev oprettet som karakterstrenge (tekst), mens losses-kolonnen er numerisk. Dette er en almindelig situation, når data importeres fra eksterne kilder.
Nu ønsker vi at beregne en ny kolonne, net_wins, ved at trække tab fra sejre:
> df$net_wins <- df$wins - df$losses Error in df$wins - df$losses: non-numeric argument to binary operator
Vi får den velkendte fejl. Lad os verificere kolonnernes datatyper:
> class(df$wins) [1] "character" > class(df$losses) [1] "numeric"
Diagnosen er klar. Vi skal konvertere df$wins til en numerisk type, før vi kan udføre subtraktionen. Løsningen er igen at bruge as.numeric():
> df$wins <- as.numeric(df$wins) > df$net_wins <- df$wins - df$losses
Nu kører koden uden fejl, og vores dataframe opdateres korrekt med den nye kolonne net_wins, som viser den månedlige difference mellem sejre og tab.
Et andet almindeligt scenarie: diff() funktionen
Fejlen er ikke begrænset til simple aritmetiske operatorer. Den kan også opstå i funktioner, der internt udfører matematiske beregninger. Et godt eksempel er diff()-funktionen, som beregner forskellen mellem på hinanden følgende elementer i en vektor.
Hvis vi prøver at bruge diff() på vores oprindelige wins-kolonne (som er af typen character):
> diff(df$wins) # Antager at df$wins stadig er 'character' Error in r[i1] - r[-length(r):-(length(r) - lag + 1L)]: non-numeric argument to binary operator
Fejlmeddelelsen er lidt mere kryptisk, men kernen er den samme. Internt forsøger diff() at trække værdier fra hinanden (f.eks. '7' - '10'), hvilket fejler, fordi de er tekst. Løsningen er identisk: konverter først dataene til numerisk format.

> diff(as.numeric(df$wins)) [1] -3 1 4 -7 -1 6 -2 1 -2 -5 9
Ved at pakke df$wins ind i as.numeric(), sikrer vi, at diff() modtager de tal, den forventer, og vi får det ønskede resultat: ændringen i antal sejre fra måned til måned.
Tabel: Almindelige faldgruber og løsninger
For at give et hurtigt overblik har vi samlet de typiske scenarier, hvor denne fejl opstår, samt den direkte løsning.
| Problem | Kode der fejler (Eksempel) | Årsag | Løsning |
|---|---|---|---|
| Simpel aritmetik | 10 * '2' | '2' er en tekststreng (character). | 10 * as.numeric('2') |
| DataFrame operation | df$col_a / df$col_b | En af kolonnerne (eller begge) er ikke numerisk. | as.numeric(df$col_a) / as.numeric(df$col_b) |
Funktioner (f.eks. diff, sum) | sum(c('1', '5', '10')) | Vektoren indeholder tekst-elementer. | sum(as.numeric(c('1', '5', '10'))) |
| Konvertering af ikke-tal | as.numeric('fem') | Teksten kan ikke fortolkes som et tal. | Resultatet bliver NA. Data skal renses først. |
Ofte Stillede Spørgsmål (FAQ)
Sp: Hvad betyder "binær operator" egentlig?
Sv: Det er et teknisk udtryk for en operation, der virker på to værdier. Tænk på + i udtrykket 2 + 3. Operatoren (+) tager de to operander (2 og 3) og producerer et resultat (5).
Sp: Hvad sker der, hvis jeg bruger as.numeric() på en tekst, der ikke er et tal (f.eks. "hej")?
Sv: Dette er et vigtigt punkt. Hvis R ikke kan fortolke teksten som et tal, vil as.numeric() konvertere værdien til NA (Not Available) og give en advarsel: NAs introduced by coercion. Dette er nyttigt til at identificere problematiske værdier i dit datasæt, som kræver yderligere datarensning.

Sp: Gælder denne fejl kun for `+` og `-`?
Sv: Nej, fejlen gælder for alle binære aritmetiske operatorer, herunder multiplikation (*), division (/), eksponentiering (^) og modulus (%%). Enhver matematisk operation, der forventer tal, vil fejle, hvis den modtager tekst.
Sp: Min kolonne indeholder komma som decimaltegn (f.eks. "3,14"). as.numeric() laver det om til NA. Hvad gør jeg?
Sv: Dette er en klassisk udfordring med data fra europæiske lande. R forventer som standard et punktum som decimaltegn. Før du kan konvertere til numerisk, skal du erstatte alle kommaer med punktummer. Dette kan gøres med gsub()-funktionen: my_vector <- gsub(",", ".", my_vector). Efter dette trin kan du trygt bruge as.numeric(my_vector).
At mestre håndteringen af datatyper er en fundamental færdighed i R. Fejlen non-numeric argument to binary operator er ikke en hindring, men snarere en nyttig påmindelse om at være opmærksom på arten af dine data. Ved konsekvent at tjekke datatyper med class() eller str() og anvende as.numeric(), hvor det er nødvendigt, kan du sikre, at dine beregninger kører problemfrit og din dataanalyse bliver mere pålidelig.
Hvis du vil læse andre artikler, der ligner Løs fejlen: Ikke-numerisk argument i R, kan du besøge kategorien Teknologi.
