0

Pandas Dataframe's query method can refer to variables in the environment by prefixing them with an ‘@’ character like @a, ex:

seq = [1,2,3,4]
df.query('col1.isin(@seq)')

The method df.query can access the calling context and assign the seq variable value to @seq. I want to add this function in JavaScript, but how to access the function calling context in JavaScript?

1 Answer 1

4

Pandas is built on Python, which is different from JavaScript. (You knew that, of course, but... 🙂)

If we had code like your example in JavaScript, there would be no way for the query function to access the value of the seq local variable (I'm assuming it's local, not global). It just has no way to reach it.

If we wanted similar functionality, we'd probably use a tagged template function:

seq = [1,2,3,4];
df.query`col1.isin(${seq})`;

(That's a tagged function call, one of two/three kinds of function calls in JavaScript that don't use ().)

That creates a template object and calls df.query with that template object and an argument for each substitution (${...}) in the template. The function still doesn't reach out and get it, it's the template literal (the bit in backticks) that gets the value, which is then passed to the function.

Just for illustration:

function logArray(label, array) {
    console.log(label + ":");
    array.forEach((element, index) => {
        console.log(`  ${index}: ${JSON.stringify(element)}`);
    });
}
const df = {
    query(template, ...args) {
        logArray("template", template);
        logArray("args", args);
    }
};

const seq = [1,2,3,4];
df.query`col1.isin(${seq})`;

Note that what gets passed to the function is the actual array, not a string version of it, so we can use that array to see if col1 is in [1,2,3,4], like this:

const df = {
    col1: 2,
    query(template, ...args) {
        // (You'd need to have some parser here for the DSL aspects
        // of your query; this is just a hardcoded example)
        if (template[1] === ".isin(") {
            // In `${"col1"}.isin(${seq})`, args[0] will be the
            // string "col1" and args[1] will be the array from
            // `seq` 
            return args[1].includes(this[args[0]]);
        } else {
            throw new Error(`Unknown expression`);
        }
    }
};

let seq = [1,2,3,4];
let result = df.query`${"col1"}.isin(${seq})`; 
console.log(result);    // true, because df.col1 is 2 and that's
                        // in [1,2,3,4]

seq = [5,6,7,8];
result = df.query`${"col1"}.isin(${seq})`;
console.log(result);    // false, because df.col1 is 2 and that's not
                        // in [5,6,7,8]

Sign up to request clarification or add additional context in comments.

1 Comment

For what it's worth, I go into tagged template functions in some detail in Chapter 10 of my recent book JavaScript: The New Toys. Links in my profile if you're interested.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.