I am coming from PHP background and still trying to get my head around R.
For instance, I can easily loop an array in PHP and manipulate the data,
$array = [
"site1" => 9
"site2" => 10
"site3" => 18
"site4" => 28
]
foreach($array as $index => $id) {
echo $id . '<br/>';
}
result,
9
10
18
28
But in R, I have this data frame for instance,
siteKey siteCode
1 site1 9
2 site2 10
3 site3 18
4 site4 28
loop,
for(i in 1:length(sites.df$siteKey)) {
print(sites.df$siteCode)
}
result,
[1] "9" "10" "18" "28"
[1] "9" "10" "18" "28"
[1] "9" "10" "18" "28"
[1] "9" "10" "18" "28"
I thought it should be this result below?
"9"
"10"
"18"
"28"
Any idea how I can use the R loop to get the result above that I need?
EDIT:
The query,
# Prepare SQL query1.
dataQuery <- "SELECT
*
FROM speckdata AS s
LEFT JOIN weatherunderground AS w
ON s.wid_timestamp = w.wid_timestamp
LEFT JOIN nodes AS n
ON n.nid = s.nid
AND n.datatype = 'speck'
WHERE n.nid = 'SITE'
"
Maybe better to loop this below?
#
# Data: site 1
#
# Match the pattern and replace it.
data1Query <- sub("SITE", as.character(site1), data1Query)
# Store the result in data1.
data1 = dbGetQuery(DB, data1Query)
#
# Data: site 2
#
data2Query <- sub("SITE", as.character(site2), data2Query)
# Store the result in data.
data2 = dbGetQuery(DB, data2Query)
#
# Data: site 3
#
data3Query <- sub("SITE", as.character(site3), data3Query)
# Store the result in data.
data3 = dbGetQuery(DB, data3Query)
#
# Data: site 4
#
data4Query <- sub("SITE", as.character(site4), data4Query)
# Store the result in data.
data4 = dbGetQuery(DB, data4Query)
Then merge all the data,
# Merge data sets.
set.seed(1)
dataList = list(data1, data2, data3, data4)
allData = Reduce(function(...) merge(..., all=T), dataList)
Then plot the data,
timePlot(
allData,
pollutant = c(species, condition),
avg.time = mean,
lwd = 2,
lty = 1,
type = "site",
group = TRUE,
auto.text = FALSE
)
Add a call to [i] in your loop like so...
for(i in 1:length(sites.df$siteKey)) {
print(sites.df$siteCode[i])
}
This way, each iteration will print the single instance at location [ i ].
Hopefully that makes sense.
The solution of #dsifford is ok in base R. However, I recommend to have a look at the dplyr package early in the switchover from php, because it makes things much more transparent than the hopeless mess of xapply functions (apologies to all radical base-R-ers).
library(dplyr)
site.df = data.frame(siteKey = paste0("site",1:4), siteCode = runif(4,9,28))
site.df %>%
rowwise %>%
do(print(.$siteCode))
In itself this is not really easier, but if you have additional manipulations, it makes for a smoother ride.
Your question as written is "R loop: How to use it correctly?"
You propose this code
for(i in 1:length(sites.df$siteKey)) {
print(sites.df$siteCode)
}
This code would be an example of using an R loop correctly (if you insisted on it, even though it is discouraged).
What this code is saying is for each pass print out the "column" or complete list of values for $siteCode. The loop is repeating that print request for each site, so you are getting the same complete list for each pass.
As suggested above by #dsifford changing it to
for(i in 1:length(sites.df$siteKey)) {
print(sites.df$siteCode[i])
}
will mean that instead of printing the entire list it will print just the ith value from that list for each pass.
The new code you added has different issues, specifically you are repeating the same code over and over for each site. You might want to consider writing functions to replace the duplicate code and then feeding the functions the list of sites you are using. That is a case where a loop may possibly make sense (although it may not). But that is all a side issue from your original question.
Related
I have a table set up with 5 columns:
user_id, 5k, 10k, halfmarathon, and marathon.
I want to display the user's best times on a user page for each distance of run. The user will be able to update any of the times which creates a new row and the rest of the columns are set to null. So for example,
Row 1 is:
user_id: 5, 5k: null, 10k: 45:00, half: null, marathon: null.
Then the user runs another 10k and gets a better time, plus wants to update their 5k time :
Row 2 is then:
user_id: 5, 5k: 15:53, 10k: 40:40, half: null, marathon: null.
When I run the following SQL query
$query = "SELECT MIN(5k), MIN(10k), MIN(halfmartahon), MIN(marathon)
FROM Times
WHERE user_id = ".$userID."
GROUP BY user_id";
$db->query($query);
//Assign Result Set
$user_benchmarks = $db->single();`
I get an array that is correct when I vardump() (I am storing the times in seconds) :
object(stdClass)#18 (4) { ["MIN(5k)"]=> string(3) "953" ["MIN(10k)"]=> string(4) "2440" ["MIN(halfmarathon)"]=> string(1) "0" ["MIN(marathon)"]=> string(1) "0" }
However, when I try to echo this, so $user_benchmarks->5k it doesn't show anything and when I run print_r($user_benchmarks->5k) it comes back as NULL.
Has anyone encountered this / know what's happening? I've also tried turning the string to an integer before printing it to no avail - still get NULL.
var_dump already showed you exactly what keys to use:
object(stdClass)#18 (4) { ["MIN(5k)"]=> string(3) "953"
^^^^^^^
so why are you using
$user_benchmarks->5k
^^^
?
It's because the "5k" property of the $user_benchmarks object doesn't exist. You need to access the "MIN(5k)" property instead. So for example:
echo $user_benchmarks->{"MIN(5k)"};
On the other hand you can change the query to something like this:
SELECT MIN(5k) AS `5k`, MIN(10k) AS `10k` ...
Then you will be able to access properties "5k" and "10k" just like you wanted.
Use
SELECT MIN(5k) as 5k,
MIN(10k) as 10k,
MIN(halfmartahon) as halfmartahon,
MIN(marathon) as marathon
I want to read two integers on two lines like:
4
5
This code works:
fscanf(STDIN,"%d",$num);
fscanf(STDIN,"%d",$v);
But I wonder if there's a shorter way to write this? (For more variables, I don't want to write a statement for each variable) Like:
//The following two lines leaves the second variable to be NULL
fscanf(STDIN,"%d%d",$num,$v);
fscanf(STDIN,"%d\n%d",$num,$v);
Update: I solved this using the method provided in the answer to read an array and list to assign variables from an array.
Consider this example:
<?php
$formatCatalog = '%d,%s,%s,%d';
$inputValues = [];
foreach (explode(',', $formatCatalog) as $formatEntry) {
fscanf(STDIN, trim($formatEntry), $inputValues[]);
}
var_dump($inputValues);
When executing and feeding it with
1
foo
bar
4
you will get this output:
array(4) {
[0] =>
int(1)
[1] =>
string(3) "foo"
[2] =>
string(3) "bar"
[3] =>
int(4)
}
Bottom line: you certainly can use loops or similar for the purpose and this can shorten your code a bit. Most of all it simplifies its maintenance. However if you want to specify a format to read with each iteration, then you do need to specify that format somewhere. That is why shortening the code is limited...
Things are different if you do not want to handle different types of input formats. In that case you can use a generic loop:
<?php
$inputValues = [];
while (!feof(STDIN)) {
fscanf(STDIN, '%d', $inputValues[]);
}
var_dump($inputValues);
Now if you feed this with
1
2
3
on standard input and then detach the input (by pressing CTRL-D for example), then the output you get is:
array(3) {
[0] =>
int(1)
[1] =>
int(2)
[2] =>
int(3)
}
The same code is obviously usable with input redirection, so you can feed a file into the script which makes detaching the standard input obsolete...
If you can in your code, try to implement a array :
fscanf(STDIN, "%d\n", $n);
$num=array();
while($n--){
fscanf(STDIN, "%d\n", $num[]);
}
print_r($num);
I'm working with a large set of nested arrays in PHP. The data originally started as a JSON data object that was converted with json_decode true. I've been able to navigate the resulting nested array without too much issue up till now. I've run into the following problem.
Scores
Team1
Info1
Info2
Element1
Element2
**Info3**
Element1
Item1
Item2
Element2
Item1
Item2
**Info3**
Element1
Item1
Item2
Element2
Item1
Item2
The problem is that Info3 are two distinct arrays with their own collections of data that I need to extract, but they have the same exact name. Running something like:
echo $Scores['Team1']['Info3'][0]['Item1']
Works to a degree; but it only captures the items of the elements of the last Info3 instance. Info3 instances further up the chain are ignored. I've also tried specifying the instance of the array I want specifically, like so:
$echo $Scores['Team1'][3]['Element1']['Item1']
Which is very similar to the above but for some reason doesn't work. It's as if the Element arrays are keyed, but the Info arrays are not. I've also tried a foreach loop through Team1 and taking action only if the value was equal to Info3, but again no joy. To further complicate things, the number of Info3 arrays is itself variable, number 0-5, so my capture has to be similarly dynamic.
Edit: Adding a JSON snippet, as requested.
"scores": {
"team1": {
"info1": 0,
"info2": [
{
"element1": 1,
"element2": 144568658
},
{
"element1": 2,
"element2": 132020087
}
]
,
"info3": [
{
"item1": 5462,
"item2": 1
}
]
,
"info3": [
{
"item1": 5608,
"item2": 1
},
{
"item1": 5611,
"item2": 1
}
]
,
"info3": [
{
"item1": 5127,
"item2": 1
}
]
},
"team2": { etc...
Edit: Thanks to everyone who took time to answer. Seems the problem with not with my coding attempts but with the JSON source being malformed.
Based off the comment from Jujunol we came up with this workaround for the bad JSON data:
$info3Count = substr_count($jsonString, '"info3": [');
$c = 1;
while ($c <= $info3Count) {
$pos = strpos($jsonString, '"info3": [');
$jsonString = substr_replace($jsonString, '"info3-'.$c.'": [', $pos,
strlen('"info3": ['));
$c++;
}
Basically, we imported the JSON as raw text, hunted through it for info3 instances and appended a -n to the end of it where n was a simple counter. This rendered each instance of info3 unique enough for a successful json_decode.
I have a variable that is dynamic and updates once every day from a cache file, but when I wish to display the variable it pulls nothing although my cache file has the information stored.
This is an example of what I am trying to do...
$var1 = "1"; // Dynamic info that is previously pulled from the cache file.
$var2 = array (
"0" => "2",
"1" => "3" );
Now I want to display the content of a certain part of the array...
echo "Test ".$var2['$var1'];
This is meant to output: Test 3
And if $var1 was a 0 it would output: Test 2
I have tried this many other ways, including changing the ' to ", or not even including them, it either displays a PHP error or it displays nothing apart from the "Test" text.
EDIT#1:
Ok, so this is to explain what I am doing a little bit better.
First I pull from a file and replace anything that comes with it that I don't need..
$myFile = "http://someserver.com/afile.txt";
$lines = file($myFile);
$ngender = preg_replace('/Gender=/', '', $lines[3]);
Now, I know that the above code works fine, its when I get to the array that I have problems..
$ngen = array (
1 => "Male",
2 => "Female"
);
Then I use $ngen[$ngender]; to store it into the xml file, but it don't store anything. This is actually I am trying to do before I store it into the xml file.
It should be:
echo "Test ".$var2[$var1];
$var1 is a variable so it should no be in ''.
A few things:
Not all PHP arrays are associative. The following is valid and more efficient:
$var2 = array(1 => "Male", 2 => "Female");
Variable names don't need to be stringified inside of statements. Your specific problem is caused because '$var2' would evaluate to the literal string $var2, while "$var2" would evaluate to "1".
So the correct code:
$var1 = "1"; // Dynamic info that is previously pulled from the cache file.
$var2 = array(1 => "Male", 2 => "Female");
echo "Test ".$var2[$var1];
The error you've posted on the other answer's comment suggest that $var1 isn't what you think it is. Make sure.
I have the following which works great, but now what I want to do is if a user types [MAP] then I want to get the word MAP
I also want allow users to send things like [MAP = array("LOCATION"=>"Melbourne Australia")]
and for the PHP to make map a array so I can then send it to a function later on
I currently do the following
$map = strpos($stringtocheck, "[MAP]");
But the issue here, is if we have a number of [] with different insides like [BOLD], [INSERT] etc then it wont find it and put it in its own $
and also it means we need to know what the array is field with or anything like that
A simple regex will pull info out of square brackets:
$s = 'Yo be [diggin] [my leet] scriptzors!';
$matches = null;
preg_match_all('/\[(.*?)\]/', $s, $matches);
var_dump($matches[1]);
Result:
array(2) {
[0]=>
string(6) "diggin"
[1]=>
string(7) "my leet"
}
Example: http://codepad.viper-7.com/erBpuB