I have a column with 10 random numbers, from that I want to create a new column that have switched places for every pair, see example for how I mean. How would you do that?
column newcolumn
1 5
5 1
7 6
6 7
25 67
67 25
-10 2
2 -10
-50 36
36 -50
Taking advantage of the fact that R will replicate smaller vectors when adding them to larger vectors, you can:
a <- data.frame(column=c(1,5,7,6,25,67,-10,2,50,36))
a$newColumn <- a$column[seq(nrow(a)) + c(1, -1)]
Something like this.
a <- data.frame(column=c(1,5,7,6,25,67,-10,2,50,36))
a$newColumn <- 0
a[seq(1,nrow(a),by=2),"newColumn"]<-a[seq(2,nrow(a),by=2),"column"]
a[seq(2,nrow(a),by=2),"newColumn"]<-a[seq(1,nrow(a),by=2),"column"]
# results
column newColumn
1 1 5
2 5 1
3 7 6
4 6 7
5 25 67
6 67 25
7 -10 2
8 2 -10
9 50 36
10 36 50
Here is a base R one-liner: We can cast column as 2 x nrow(df)/2 matrix, swap rows, and recast as vector.
df$newcolumn <- c(matrix(df$column, ncol = nrow(df) / 2)[c(2,1), ]);
# column newcolumn
#1 1 5
#2 5 1
#3 7 6
#4 6 7
#5 25 67
#6 67 25
#7 -10 2
#8 2 -10
#9 -50 36
#10 36 -50
Sample data
df <- read.table(text =
"column
1
5
7
6
25
67
-10
2
-50
36", header = T)
Another option would be to use ave and rev
transform(df, newCol = ave(x = df$column, rep(1:5, each = 2), FUN = rev))
# column newCol
#1 1 5
#2 5 1
#3 7 6
#4 6 7
#5 25 67
#6 67 25
#7 -10 2
#8 2 -10
#9 -50 36
#10 36 -50
The part rep(1:5, each = 2) creates a grouping variable ("pairs") for each of which we reverse the elements.
Here's a compact way:
a$new_col <- c(matrix(a$column,2)[2:1,])
# column new_col
# 1 1 5
# 2 5 1
# 3 7 6
# 4 6 7
# 5 25 67
# 6 67 25
# 7 -10 2
# 8 2 -10
# 9 50 36
# 10 36 50
The idea is to write in a 2 row matrix, switch the rows, and unfold back in a vector.
Related
I need to create bins for every completed rotation e.g. 360° and bins will be of varying lengths. I have created a for loop but with 100,000+ rows it is slow. I tried to implement using dplyr and/or other non-loop methods but am unclear where and how to declare the cutoffs. None of the examples I found for either dplyr or cut() seemed to address my problem.
Sample data:
x <- c(seq(90, .5, length.out = 3),
seq(359.5, .2, length.out = 5),
seq(358.9, .8, length.out = 8),
seq(359.2, .3, length.out = 11),
seq(358.3, .1, length.out = 15))
df <- data.frame(x)
df$bin <- NA
df[1,2] <- 1
For loop:
for(i in 2:nrow(df)) {
if(df[i,1] < df[i-1,1]) {
df[i,2] <- df[i-1,2]
} else {
df[i,2] <- df[i-1,2] + 1
}
}
How are the results in df$bin achieved without using a loop?
It looks like you could do:
df$binnew <- cumsum(c(1, diff(df$x) > 0))
Compare:
x bin binnew
1 90.00000 1 1
2 45.25000 1 1
3 0.50000 1 1
4 359.50000 2 2
5 269.67500 2 2
6 179.85000 2 2
7 90.02500 2 2
8 0.20000 2 2
9 358.90000 3 3
10 307.74286 3 3
11 256.58571 3 3
12 205.42857 3 3
13 154.27143 3 3
14 103.11429 3 3
15 51.95714 3 3
16 0.80000 3 3
17 359.20000 4 4
18 323.31000 4 4
19 287.42000 4 4
20 251.53000 4 4
21 215.64000 4 4
22 179.75000 4 4
23 143.86000 4 4
24 107.97000 4 4
25 72.08000 4 4
26 36.19000 4 4
27 0.30000 4 4
28 358.30000 5 5
29 332.71429 5 5
30 307.12857 5 5
31 281.54286 5 5
32 255.95714 5 5
33 230.37143 5 5
34 204.78571 5 5
35 179.20000 5 5
36 153.61429 5 5
37 128.02857 5 5
38 102.44286 5 5
39 76.85714 5 5
40 51.27143 5 5
41 25.68571 5 5
42 0.10000 5 5
I wrote a simple function that produces all combinations of the input (a vector). Here the input vector is basically a sequence of 4 coordinates (x, y) as mentioned inside the function as a, b,c, and d.
intervals<-function(x1,y1,x2,y2,x3,y3,x4,y4){
a<-c(x1,y1)
b<-c(x2,y2)
c<-c(x3,y3)
d<-c(x4,y4)
union<-expand.grid(a,b,c,d)
union
}
intervals(2,10,3,90,6,50,82,7)
> intervals(2,10,3,90,6,50,82,7)
Var1 Var2 Var3 Var4
1 2 3 6 82
2 10 3 6 82
3 2 90 6 82
4 10 90 6 82
5 2 3 50 82
6 10 3 50 82
7 2 90 50 82
8 10 90 50 82
9 2 3 6 7
10 10 3 6 7
11 2 90 6 7
12 10 90 6 7
13 2 3 50 7
14 10 3 50 7
15 2 90 50 7
16 10 90 50 7
>
Now I want to find (max of x) and (min of y) for each row of the given output. E.g. row 2: we have 4 values (10, 3, 6, 82). Here (3,6,82) are from x (x2,x3,x4) and 10 is basically from y (y1). Thus max of x is 82, and the min of y is 10.
So what I want is two values from each row.
I do not actually know how to approach this kind of logical command. Any idea or suggestions?
You can pass x and y vector separately to the function. Use expand.grid to create all combinations of the vector and get max of x and min of y from each row.
intervals<-function(x, y){
tmp <- do.call(expand.grid, rbind.data.frame(x, y))
names(tmp) <- paste0('col', seq_along(tmp))
result <- t(apply(tmp, 1, function(p) {
suppressWarnings(c(max(p[p %in% x]), min(p[p %in% y])))
}))
result[is.infinite(result)] <- NA
result <- as.data.frame(result)
names(result) <- c('max_x', 'min_x')
result
}
intervals(c(2,3,6,82), c(10, 90, 50, 7))
# max_x min_x
#1 82 NA
#2 82 10
#3 82 90
#4 82 10
#5 82 50
#6 82 10
#7 82 50
#8 82 10
#9 6 7
#10 6 7
#11 6 7
#12 6 7
#13 3 7
#14 3 7
#15 2 7
#16 NA 7
I have several seperate data frames that I would like to keep separated because merging them together would create a very large element.
However, there are variables from another data frame that I would like to merge with all of them now.
Here is an example of what I would like to do:
df1 <- data.frame(ID1 = c(1:10), Var1 = rep(c(1,0),5))
df2 <- data.frame(ID1 = c(1:10), Var2 = c(21:30))
dfs <- Filter(function(x) is(x, "data.frame"), mget(ls()))
mergewith <- data.frame(ID1 = c(1:10), ID2 = c(41:50))
My goal is that df1 and df2 will look like this:
df1
ID1 Var1 ID2
1 1 1 41
2 2 0 42
3 3 1 43
4 4 0 44
5 5 1 45
6 6 0 46
7 7 1 47
8 8 0 48
9 9 1 49
10 10 0 50
df2
ID1 Var2 ID2
1 1 21 41
2 2 22 42
3 3 23 43
4 4 24 44
5 5 25 45
6 6 26 46
7 7 27 47
8 8 28 48
9 9 29 49
10 10 30 50
What I have tried so far is:
dat = lapply(dfs,function(x){
merge(names(x), mergewith, by = "ID1");x})
list2env(dat,.GlobalEnv)
However, then I get the following message:
"'by' must specify a uniquely valid column"
Is it possible to do this without using a loop?
You can try Map
> Map(function(x, y) merge(x, y, by = "ID1"), dfs, list(mergewith))
[[1]]
ID1 Var1 ID2
1 1 1 41
2 2 0 42
3 3 1 43
4 4 0 44
5 5 1 45
6 6 0 46
7 7 1 47
8 8 0 48
9 9 1 49
10 10 0 50
[[2]]
ID1 Var2 ID2
1 1 21 41
2 2 22 42
3 3 23 43
4 4 24 44
5 5 25 45
6 6 26 46
7 7 27 47
8 8 28 48
9 9 29 49
10 10 30 50
You can use lapply to merge all the dataframes in dfs with mergewith. Use list2env to get the changed dataframes in the global environment.
list2env(lapply(dfs, function(x) merge(x, mergewith, by = 'ID1')), .GlobalEnv)
Having the following list, I would like the result of the frequency to be multiplied by its index value raised to 3. How could I do it?
data<-c(1,1,2,2,3,34,65,78,65,3)
table(data)
data
1 2 3 34 65 78
2 2 2 1 2 1
Expected:
1 2 3 34 65 78
2 8*2 27*2 39304*1 274625*2 474552*1
Thanks
with(rle(sort(data)), lengths*values^3)
#[1] 2 16 54 39304 549250 474552
OR
x = table(data)
x*as.numeric(names(x))^3
#data
#1 2 3 34 65 78
#2 16 54 39304 549250 474552
You could consider tapply:
res <- tapply(data, data, function(x) (x[1]^3) * length(x))
#1 2 3 34 65 78
#2 16 54 39304 549250 474552
Note as beautiful as the other answers but a multi-step solution.
Data:
data<-c(1,1,2,2,3,34,65,78,65,3)
data <- as.data.frame(table(data))
Solve the problem:
data$data <- as.numeric(as.character(data$data))
data$powers <- data$data**3
data$final <- data$Freq * data$powers
Result:
data Freq powers final
1 1 2 1 2
2 2 2 8 16
3 3 2 27 54
4 34 1 39304 39304
5 65 2 274625 549250
6 78 1 474552 474552
I am trying to get all combinations of values per group. I want to prevent combination of values between different groups.
To create all combinations of values (no matter which group the value belongs) vaI can use:
expand.grid(value, value)
Awaited result should be the subset of result of previous command.
Example:
#base data
value = c(1,3,5, 1,5,7,9, 2)
group = c("a", "a", "a","b","b","b","b", "c")
base <- data.frame(value, group)
#creating ALL combinations of value
allComb <- expand.grid(base$value, base$value)
#awaited result is subset of allComb.
#Note: first colums shows the number of row from allComb.
#Empty rows are separating combinations per group and are shown only for clarification.
Var1 Var2
1 1 1
2 3 1
3 5 1
11 1 3
12 3 3
13 5 3
21 1 5
22 3 5
23 5 5
34 1 1
35 5 1
36 7 1
37 9 1
44 1 5
45 5 5
46 7 5
47 9 5
54 1 7
55 5 7
56 7 7
57 9 7
64 1 9
65 5 9
66 7 9
67 9 9
78 2 2