I have a below stdin input and I am trying to convert this input to a list.
Input
input <- suppressWarnings(readLines(stdin(), n=31))
8 30
a s 3
b s 5
s a 3
b a 1
c a 10
d a 11
s b 5
a b 3
c b 2
d b 3
a c 10
b c 2
d c 3
e c 7
f c 12
a d 15
b d 7
c d 2
e d 11
f d 2
c e 7
d e 11
f e 3
z e 2
c f 12
d f 2
e f 3
z f 2
e z 2
f z 2
Line 1 first value denotes total number of alphabets , Second value denotes total number of rows.
From Line 2 to Line n. First value denotes starting node , second is ending node and third is cost.
I want to group the alphabets and cost as a list in below manner.
Expected output
> alphabets
$s
[1] "a" "b"
$a
[1] "s" "b" "c" "d"
$b
[1] "s" "a" "c" "d"
$c
[1] "a" "b" "d" "e" "f"
$d
[1] "a" "b" "c" "e" "f"
$e
[1] "c" "d" "f" "z"
$f
[1] "c" "d" "e" "z"
$z
[1] "e" "f"
> cost
$s
[1] 3 5
$a
[1] 3 1 10 11
$b
[1] 5 3 2 3
$c
[1] 10 2 3 7 12
$d
[1] 15 7 2 11 2
$e
[1] 7 11 3 2
$f
[1] 12 2 3 2
$z
[1] 2 2
Any suggestions from where to start.?
Does this give you what you want? I convert your input to a data.frame and the split based on your second column. The output of this differs slightly from yours since split will sort. If you do not want that, you can order the output based on the input.
df <- read.table(textConnection(input[-1]))
alphabets <- split(df$V1, df$V2)
cost <- split(df$V3, df$V2)
# you can do this to reorder how you had it
order <- unique(df$V2)
alphabets[order]
cost[order]
Related
Suppose my data is ordered as listed tibbles with a corresponding tibble that provides further info. Row "a" in infos refers thus to tibble "a" from the list.
list_in <- list(a=tibble(I=c(6:10),
II=c(2:6),
III=letters[1:5]),
b=tibble(I=c(1:5),
II=c(2:6),
III=letters[2:6]),
c=tibble(I=c(7:11),
II=c(3:7),
III=letters[5:9]))
infos <- tibble(id=c("a","b","c"),
weights=c(1:3),
grades=letters[4:6])
In order to do further calculations, is there a way to use lapply or a loop to append list_in, so that list_out also contains the corresponding values from infos? The expected output would look like this:
# install.packages("rlist")
library(rlist)
list_out <- list((list.append(list_in$a, weights=infos$weights[1], grades=infos$grades[1])),
(list.append(list_in$b, weights=infos$weights[2], grades=infos$grades[2])),
(list.append(list_in$c, weights=infos$weights[3], grades=infos$grades[3])))
but this way to get there feels very awkward and only works for very small data sets.
Thanks in advance!
You can use lapply and c() to append each tibble with the corresponding row of infos.
list_out2 <- lapply(names(list_in), \(x) {
c(list_in[[x]], infos[infos$id == x, -1])
})
all.equal(list_out, list_out2)
# [1] TRUE
list_out2
[[1]]
[[1]]$I
[1] 6 7 8 9 10
[[1]]$II
[1] 2 3 4 5 6
[[1]]$III
[1] "a" "b" "c" "d" "e"
[[1]]$weights
[1] 1
[[1]]$grades
[1] "d"
[[2]]
[[2]]$I
[1] 1 2 3 4 5
[[2]]$II
[1] 2 3 4 5 6
[[2]]$III
[1] "b" "c" "d" "e" "f"
[[2]]$weights
[1] 2
[[2]]$grades
[1] "e"
[[3]]
[[3]]$I
[1] 7 8 9 10 11
[[3]]$II
[1] 3 4 5 6 7
[[3]]$III
[1] "e" "f" "g" "h" "i"
[[3]]$weights
[1] 3
[[3]]$grades
[1] "f"
You can do a left_join between the tibble in the list and the extra info:
append_info <- function(n) {
out <- list_in[[n]] %>%
mutate(id = n) %>%
left_join(infos, by = 'id') %>%
select(-id)
return(out)
}
lapply(names(list_in), append_info)
Using Map
Map(c, list_in, split(infos[-1], infos$id))
-output
$a
$a$I
[1] 6 7 8 9 10
$a$II
[1] 2 3 4 5 6
$a$III
[1] "a" "b" "c" "d" "e"
$a$weights
[1] 1
$a$grades
[1] "d"
$b
$b$I
[1] 1 2 3 4 5
$b$II
[1] 2 3 4 5 6
$b$III
[1] "b" "c" "d" "e" "f"
$b$weights
[1] 2
$b$grades
[1] "e"
$c
$c$I
[1] 7 8 9 10 11
$c$II
[1] 3 4 5 6 7
$c$III
[1] "e" "f" "g" "h" "i"
$c$weights
[1] 3
$c$grades
[1] "f"
Hopefully this is simple, but it seems tricky to explain!
I want to combine two matrices in R, but I'd like to take the first two columns from the first matrix as the first two rows of the combined matrix, then the first column in the second matrix as the third column in the new matrix, then the 4th and 5th columns of the new matrix would be the 3rd and 4th from the first matrix and so and so forth. All matrices have the same row names and same number of rows
Matrix 1:
1 2 1 2 1 2
A a b c d e f
B a b c d e f
C a b c d e f
Matrix 2:
3 3 3
A x x x
B y y y
C z z z
Desired Matrix:
1 2 3 1 2 3 1 2 3
A a b x c d x e f x
B a b y c d y e f y
C a b z c d z e f z
In my example I need this (1,2)(3)(1,2)(3) configuration but as the post title suggests it would be cool to have a generic way of doing this for any configuration of columns from the matrices to be merged.
Make a set of column indexes and then subset a cbind-ed version of the pair of matrices:
grp1 <- 2
grp2 <- 1
sel <- c(rbind(
matrix(1:ncol(mat1),ncol=ncol(mat1)/grp1),
matrix(1:ncol(mat2),ncol=ncol(mat2)/grp2) + ncol(mat1)
))
# 'sel' looks like this before coercion to a vector.
# You can see how the alternating numbers fit together here:
# [,1] [,2] [,3]
#[1,] 1 3 5
#[2,] 2 4 6
#[3,] 7 8 9
cbind(mat1,mat2)[,sel]
1 2 3 1 2 3 1 2 3
A "a" "b" "x" "c" "d" "x" "e" "f" "x"
B "a" "b" "y" "c" "d" "y" "e" "f" "y"
C "a" "b" "z" "c" "d" "z" "e" "f" "z"
Using the following objects as mat1 and mat2:
mat1 <- as.matrix(read.table(text="1 2 1 2 1 2
A a b c d e f
B a b c d e f
C a b c d e f", header=TRUE, check.names=FALSE, stringsAsFactors=FALSE))
mat2 <- as.matrix(read.table(text="3 3 3
A x x x
B y y y
C z z z", header=TRUE, check.names=FALSE, stringsAsFactors=FALSE))
How can I get all the combinations of a list with duplicates. By duplicates I mean an element with itself. I am building a symmetric matrix.
names.list<-c("A","B","C")
as.data.frame(t(combn(names.list,2)))
Result is:
V1 V2
1 A B
2 A C
3 B C
When I want:
V1 V2
1 A A
2 A B
3 A C
4 B B
5 B C
6 C C
Or even:
V1 V2
1 A A
2 A B
3 A C
4 B A
5 B B
6 B C
7 C A
8 C B
9 C C
But my matrices are large so I would like to keep combinations to a minimum (so preferably the second result), since more combinations = more computations = larger run times..
Thanks.
It sounds like you're looking for expand.grid instead of combn:
expand.grid(names.list, names.list)
# Var1 Var2
# 1 A A
# 2 B A
# 3 C A
# 4 A B
# 5 B B
# 6 C B
# 7 A C
# 8 B C
# 9 C C
Update
There's also combinations from "gtools" which would give you your preferred output.
library(gtools)
combinations(3, 2, names.list, repeats = TRUE)
# [,1] [,2]
# [1,] "A" "A"
# [2,] "A" "B"
# [3,] "A" "C"
# [4,] "B" "B"
# [5,] "B" "C"
# [6,] "C" "C"
I have 10 letters "a b c d e f g h i j" and 200 numbers from 1 to 200 with different number of instances, e.g. five 1s three 2s etc. making up 200 numbers in total.
I would like to assign each number a letter such that each letter has equal frequency.
So in this case I want 20 instances of each letter.
My problem is that I would like to randomly assign letters to numbers.
An example would be:
1 1 1 1 1 2 2 3 3 3 3 3 3 4 5 6 7 7 7 ...until 200
a a a a a e e f f f f f f d i j c c c ...until 200
Start with this-- I'm deliberately not overwriting the existing column in A
Rgames> B<-sample(letters,10)
Rgames> B
[1] "b" "m" "l" "v" "c" "t" "s" "i" "n" "j"
Rgames> A<-sample(1:10,10,replace=TRUE)
Rgames> A
[1] 3 3 2 8 1 5 5 8 2 6
Rgames> A.new<-B[A]
Rgames> A.new
[1] "l" "l" "m" "i" "b" "c" "c" "i" "m" "t"
Then you could cbind if desired to combine A.new and A
I have an R data frame that looks like this:
z = as.data.frame(list(Col1=c("a","c","e","g"),Col2=c("b","d","f","h"),Col3=c("1,2,5","3,5,7","9,8","1")))
> z
Col1 Col2 Col3
1 a b 1,2,5
2 c d 3,5,7
3 e f 9,8
4 g h 1
(The third column is a text column with comma-separated values.) I would like to convert it to a data frame like this:
a b 1
a b 2
a b 5
c d 3
c d 5
c d 7
e f 9
e f 8
g h 1
Can anyone suggest a way to accomplish this using apply? I'm close using the command below but it's not quite right. Any suggestions on more efficient ways to do this would be appreciated as well...
> apply(z,1,function(a){ids=strsplit(as.character(a[3]),",")[[1]];out<-c();for(id in ids){out<-rbind(out,c(a[1:2],id))};return(out)})
[[1]]
Col1 Col2
[1,] "a" "b" "1"
[2,] "a" "b" "2"
[3,] "a" "b" "5"
[[2]]
Col1 Col2
[1,] "c" "d" "3"
[2,] "c" "d" "5"
[3,] "c" "d" "7"
[[3]]
Col1 Col2
[1,] "e" "f" "9"
[2,] "e" "f" "8"
[[4]]
Col1 Col2
[1,] "g" "h" "1"
You can use ddply.
library(plyr)
ddply(z, c("Col1", "Col2"), summarize,
Col3=strsplit(as.character(Col3),",")[[1]]
)
With reshapeor reshape2
require(reshape2)
merge(cbind(z[,-3], L1=rownames(z)), melt(strsplit(as.character(z$Col3),",")))
gives
L1 Col1 Col2 value
1 1 a b 1
2 1 a b 2
3 1 a b 5
4 2 c d 3
5 2 c d 5
6 2 c d 7
7 3 e f 9
8 3 e f 8
9 4 g h 1