Come ottenere VLOOKUP per restituire la * ultima * partita?


12

Sono abituato a lavorare con VLOOKUP ma questa volta ho una sfida. Non voglio il primo valore corrispondente, ma l' ultimo. Come? (Sto lavorando con LibreOffice Calc ma una soluzione MS Excel dovrebbe essere ugualmente utile.)

Il motivo è che ho due colonne di testo con migliaia di righe, diciamo che una è un elenco di beneficiari di transazioni (Amazon, Ebay, datore di lavoro, negozio di alimentari, ecc.) E l'altra è un elenco di categorie di spesa (salari, tasse, famiglia, affitto, ecc.). Alcune transazioni non hanno sempre la stessa categoria di spesa e desidero prendere quella utilizzata più di recente. Si noti che l'elenco è ordinato per nessuna colonna (in effetti per data) e non voglio cambiare l'ordinamento.

Quello che ho (esclusa la gestione degli errori) è la solita formula "prima corrispondenza":

=VLOOKUP( 
[payee field] , [payee+category range] , [index of category column] , 
0 )

Ho visto soluzioni come questa, ma ottengo #DIV/0!errori:

=LOOKUP(2 , 1/( [payee range] = [search value] ) , [category range] )

La soluzione può essere qualsiasi formula, non necessariamente VLOOKUP. Posso anche scambiare le colonne beneficiario / categoria in giro. Solo nessuna modifica nella colonna di ordinamento, per favore.


Punti bonus per una soluzione che sceglie il valore più frequente anziché l'ultimo!

Risposte:


3

È possibile utilizzare una formula di matrice per ottenere dati dall'ultimo record corrispondente.

=INDEX(IF($A$1:$A$20="c",$B$1:$B$20),MAX(IF($A$1:$A$20="c",ROW($A$1:$A$20))))

Immettere la formula utilizzando Ctrl+ Shift+ Enter.

Funziona come la INDEX/ MATCHcostruzione di un VLOOKUP, ma con un condizionale MAXusato al posto di MATCH.

Si noti che ciò presuppone che la tabella inizi dalla riga 1. Se i dati iniziano da una riga diversa, sarà necessario regolare la ROW(...)parte sottraendo la differenza tra la riga superiore e 1.


Sono confuso da quella "c" letterale - penso che la valutazione sia sempre falsa, quindi cosa fa davvero?
Torben Gundtofte-Bruun,

Ho testato il tuo suggerimento (e verificato che fosse accettato come formula di matrice). Presumo che Col A sia beneficiario e B sia categoria, giusto? Sfortunatamente, LibreOffice restituisce "ERR: 502" che si traduce in "Argomento non valido: argomento della funzione non valido. Ad esempio, un numero negativo per la funzione SQRT (), per questo si prega di utilizzare IMSQRT ()". Ho verificato che tutte le funzioni esistano con quel nome in LibreOffice, ma mi chiedo se LibreOffice IFnon sia in grado di gestire array.
Torben Gundtofte-Bruun,

Siamo spiacenti, la letterale "c" era solo il nome del beneficiario che volevi trovare. Era una reliquia dei miei dati di esempio con cui stavo giocando. Presumo che verrà sostituito con un riferimento di cella nel tuo foglio.
Eccellente l'

@ TorbenGundtofte-Bruun Care per condividere la formula che stai utilizzando? Potrei essere in grado di risolverlo se posso vederlo. Inoltre, puoi sempre provare a scorrere la formula con Evaluate Formulaper vedere quale parte della formula sta generando l'errore. Questa funzione esiste in Excel e sarei sorpreso se LibreOffice Calc non avesse la stessa funzione.
Eccellente l'

La mia formula originale è semplice, ecco perché non è adeguata :-) =VLOOKUP(J1061;$J$2:$K$9999;2;0)dove col J contiene beneficiari e col K le categorie. Restituisce la prima partita come previsto.
Torben Gundtofte-Bruun,

2

(Rispondere qui come nessuna domanda separata per i dati ordinati.)

Se i dati sono stati ordinati, è possibile utilizzare VLOOKUPcon l' range_lookupargomento TRUE(o omesso, poiché è l'impostazione predefinita), che è ufficialmente descritta per Excel come "ricerca di una corrispondenza approssimativa".

In altre parole, per i dati ordinati:

  • impostando l'ultimo argomento su FALSErestituisce il primo valore, e
  • impostando l'ultimo argomento su TRUErestituisce l' ultimo valore.

Questo è in gran parte privo di documenti e oscuro, ma risale a VisiCalc (1979), e oggi detiene almeno in Microsoft Excel, LibreOffice Calc e Fogli Google. Alla fine è dovuto all'implementazione iniziale di LOOKUPin VisiCalc (e quindi VLOOKUPe HLOOKUP), quando non c'era un quarto parametro. Il valore viene rilevato dalla ricerca binaria , utilizzando il limite sinistro inclusivo e il limite destro esclusivo (un'implementazione comune ed elegante), che determina questo comportamento.

Tecnicamente questo significa che si avvia la ricerca con l'intervallo candidato [0, n), dove si ntrova la lunghezza dell'array, e la condizione invariante del loop è che A[imin] <= key && key < A[imax](il limite sinistro è <= il bersaglio, il limite destro, che inizia uno dopo la fine, è > il target; per convalidare, controllare i valori agli endpoint prima o verificare il risultato dopo), e successivamente bisecare e scegliere qualunque lato preservi questo invariante: per esclusione un lato lo farà, fino ad arrivare ad un intervallo con 1 termine [k, k+1), e il l'algoritmo quindi ritorna k. Non è necessario che sia una corrispondenza esatta (!): È solo la corrispondenza più vicina dal basso. In caso di corrispondenze duplicate, ciò comporta la restituzione dell'ultima corrispondenza, in quanto richiede che il valore successivo sia maggiorerispetto alla chiave (o alla fine dell'array). In caso di duplicati è necessario un comportamento, e questo è ragionevole e facile da implementare.

Questo comportamento è esplicitamente indicato in questo vecchio articolo della Microsoft Knowledge Base (enfasi aggiunta): "XL: Come restituire la prima o l'ultima corrispondenza in un array" ( Q214069 ):

È possibile utilizzare la funzione LOOKUP () per cercare un valore all'interno di un array di dati ordinati e restituire il valore corrispondente contenuto in quella posizione all'interno di un altro array. Se il valore di ricerca viene ripetuto all'interno dell'array, restituisce l'ultima corrispondenza rilevata . Questo comportamento è vero per le funzioni VLOOKUP (), HLOOKUP () e LOOKUP ().

Segue la documentazione ufficiale per alcuni fogli di calcolo; né viene indicato il comportamento "last match", ma è implicito nella documentazione di Fogli Google:

  • Microsoft Excel

    VERO presuppone che la prima colonna della tabella sia ordinata in ordine numerico o alfabetico e quindi cercherà il valore più vicino .

  • Fogli Google :

    Se is_sortedè TRUEo omesso, viene restituita la corrispondenza più vicina ( minore o uguale alla chiave di ricerca)


Quella cosa della partita più vicina mi stava facendo impazzire!
dukedave,

1

Se i valori nell'array di ricerca sono sequenziali (ovvero stai cercando il valore più grande, ad esempio la data più recente), non è nemmeno necessario utilizzare la funzione INDIRETTA. Prova questo semplice codice:

=MAX(IF($A$1:$A$20="c",$B$1:$B$20,)

Di nuovo, inserisci la formula usando CTRL + MAIUSC + INVIO


0

Ho provato il valore più frequente. Non sono sicuro che funzionerebbe in libreOffice, ma sembra funzionare in Excel

= INDEX ($ B $ 2: $ B $ 9, MATCH (MAX (- ($ A $ 2: $ A $ 9 = D2) * CONTA.PIÙ.SE ($ B $ 2: $ B $ 9, $ B $ 2: $ B $ 9, $ A $ 2 : $ A $ 9, D2)), - ($ A $ 2: $ A $ 9 = D2) * CONTA.PIÙ.SE ($ B $ 2: $ B $ 9, $ B $ 2: $ B $ 9, $ A $ 2: $ A $ 9, D2 ), 0))

La colonna A sarebbe il beneficiario, la colonna B sarebbe la categoria, D2 è il beneficiario che si desidera filtrare. Non sono sicuro del perché stia inserendo interruzioni di riga extra nella funzione sopra.

La mia funzione per trovare l'ultima cella sarebbe la seguente:

= INDIRETTO ("B" e MAX (- ($ A $ 2: $ A $ 9 = D2) * ROW ($ A $ 2: $ A $ 9)))

Indiretto mi consente di specificare la colonna che voglio restituire e trovare direttamente la riga (quindi non ho bisogno di sottrarre il numero di righe di intestazione.

Entrambe queste funzioni devono essere inserite usando Ctrl + Maiusc + Invio


0
=LOOKUP([payee field] , [payee range] , [category range])

Questo ti darà l'ultimo valore

Ricevo punti bonus per un ritardo di 3 anni?


-1

Hai #DIV/0!errori perché dovresti piuttosto scrivere la tua formula come:

=LOOKUP(2;IF(([payee range] = [search value]);1;"");[category range])

questo funzionerà e troverà l'ultima partita.

([payee range] = [search value]) : matrice booleana VERO / FALSO

IF(([payee range] = [search value]);1;"") : matrice pseudo-booleana 1 / ""

=LOOKUP(2; {pseudo-boolean matrix 1/""} );[category range]): torna sempre all'ultima 1posizione


LOOKUPfunziona solo su un elenco ordinato, l'output del tuo comarison comporterà un elenco di se 1spazi in modo non ordinato, quindi non darà il risultato corretto.
Máté Juhász,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.