Applying Some Functions to Multiple Objects

Applying some functions to multiple objects

It is generally encouraged (by the R Core team memebers) that if you have several data sets that you want to simultaneously operate on, you should keep them all in a list. In order to achieve your goal, you can simply use mget and ls to retreive them from the global environment and then simply replace with first column multiplied by 2, e.g.,

lapply(mget(ls(pattern = "[a-z]")), function(x) x <- x[1] * 2)
# $a
# X1
# 1 2
# 2 4
# 3 6
# 4 8
# 5 10
#
# $b
# X1
# 1 22
# 2 24
# 3 26
# 4 28
# 5 30

Applying same function on multiple objects in R

Create a named list :

list_all<- dplyr::lst(list_csfiles,list_tsfiles,list_dmfiles,list_tmfiles)

In the function pass data and name seperately :

newey<-function(list_files, name) {
#All the code as it is
#...
#...
#...
write.xlsx(cs_nw_full, paste0(name, ".xlsx"))
}

You can then use Map :

Map(newey, list_all, names(list_all))

Or with purrr::imap

purrr::imap(list_all, newey)

Apply a set of functions to an object

Some good answers already but throw in another option - build a pipe chain as a string then evaluate it. For example - for row 1 - eval(parse(text = "1 %>% rule1")) gives 2

eval_chain <- function(df) {
eval(parse(text = paste(c(df$data, unlist(strsplit(df$rules, ", "))), collapse=" %>% ")))
}

df$value <- sapply(1:nrow(df), function(i) df[i, ] %>% eval_chain)
# data rules value
# 1 1 rule1 2
# 2 2 rule1, rule2, rule3 125
# 3 3 rule3, rule2 28

Sequentially apply multiple functions to object using different lenses

As well as OriDrori's converge solution, you could also use either of two other Ramda functions. I always prefer lift to converge when it works; it feels more like standard FP, where converge is very much a Ramda artifact. It doesn't always do the job because of some of the variadic features of converge. But it does here, and you could write:

const calc = pipe (
over (arrLens, map (multiply (2))),
lift (set (res0sumOfDblLens) ) (
pipe (view (arrLens), sum),
identity
)
)

But that identity in either of these solutions makes me wonder if there's something better. And there is. Ramda's chain when applied to functions is what's sometimes known as the starling combinator, :: (a -> b -> c) -> (a -> b) -> a -> c. Or said a different way, chain (f, g) //~> (x) => f (g (x)) (x). And that's just what we want to apply here. So with chain, this is simplified further:

const arrLens = lensProp('arr')const res0sumOfDblLens = lensPath(['result', 'sumOfDoubled'])
const calc = pipe ( over (arrLens, map (multiply (2))), chain ( set (res0sumOfDblLens), pipe (view (arrLens), sum) ))
const obj = { arr: [2, 3], result: { sumOfDoubled: 0 }}
console .log (calc (obj))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script><script>const {lensProp, lensPath, pipe, over, map, multiply, chain, set, view, sum} = R </script>

Perform a single function on multiple object

While you've already accepted an answer, this is possible in a similar manner either natively through JavaScript 1.6/ECMAScript 5th Edition:

function logElementID(element, index, array) {
var el = array[index],
prop = el.textContent ? 'textContent' : 'innerText';
el[prop] = el.id;
}

[document.getElementById('one'), document.getElementById('two')].forEach(logElementID);

JS Fiddle demo.

Or by extending the Object prototype:

function doStuff (el) {
console.log(el);
};

Object.prototype.actOnGroup = function(func){
var els = this.length ? this : [this];
for (var i = 0, len = els.length; i<len; i++){
func(els[i]);
}
return this;
};

document.getElementsByTagName('div').actOnGroup(doStuff);
document.getElementById('one').actOnGroup(doStuff);

JS Fiddle demo.

Or by, similarly, extending the Array prototype:

function doStuff (el) {
console.log(el);
};
Array.prototype.actOnGroup = function(func){
var els = this.length ? this : [this];
for (var i = 0, len = els.length; i<len; i++){
func(els[i]);
}
return this;
};

[document.getElementById('one'), document.getElementById('two')].actOnGroup(doStuff);

JS Fiddle demo.

Incidentally, if you'd like to provide a forEach() alternative to users without (relatively) up-to-date JavaScript implementations, the Mozilla Developer Network page for forEach() offers the following as '[an] algorithm 100% true to the ECMA-262, 5th edition':

// Production steps of ECMA-262, Edition 5, 15.4.4.18
// Reference: http://es5.github.com/#x15.4.4.18
if (!Array.prototype.forEach) {

Array.prototype.forEach = function forEach(callback, thisArg) {

var T, k;

if (this == null) {
throw new TypeError("this is null or not defined");
}

// 1. Let O be the result of calling ToObject passing the |this| value as the argument.
var O = Object(this);

// 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = O.length >>> 0; // Hack to convert O.length to a UInt32

// 4. If IsCallable(callback) is false, throw a TypeError exception.
// See: http://es5.github.com/#x9.11
if ({}.toString.call(callback) !== "[object Function]") {
throw new TypeError(callback + " is not a function");
}

// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (thisArg) {
T = thisArg;
}

// 6. Let k be 0
k = 0;

// 7. Repeat, while k < len
while (k < len) {

var kValue;

// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
if (Object.prototype.hasOwnProperty.call(O, k)) {

// i. Let kValue be the result of calling the Get internal method of O with argument Pk.
kValue = O[k];

// ii. Call the Call internal method of callback with T as the this value and
// argument list containing kValue, k, and O.
callback.call(T, kValue, k, O);
}
// d. Increase k by 1.
k++;
}
// 8. return undefined
};
}

Copied verbatim, from the reference (below) from the MDN forEach() article; 01/04/2013, at 14:30.

References:

  • Array.forEach().

Passing multiple objects into a function via sapply() or lapply() while maintaining the functionality of substitute() inside the function

The usual way of handling something like this is to send the desired name to the function as well. In this case it may help to name the elements in your list with the desired names. Perhaps something like this:

f <- c('1', '2', '3')
d <- lapply(f, read.table)
names(d) <- f # optionally some other names

MyFunc <- function(dat, nam) {
plot(dat[1]~dat[2])
title(main=nam)
dat.new <- some.manipulations(dat)
write.csv(dat.new, file=paste(nam, ".csv", sep=""))
}

lapply(names(d), function(n) MyFunc(d[[n]], n))


Related Topics



Leave a reply



Submit