I have 3 rows
first <- LETTERS[1:9]
second <- c(1:9)
third <- letters[1:9]
> first
[1] "A" "B" "C" "D" "E" "F" "G" "H" "I"
> second
[1] 1 2 3 4 5 6 7 8 9
> third
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i"
I want the output vector of 9 elements with new line like that
"A "B
1 2
a" b" and so on
I try to use loop but it doesn't work
y <-c()
z <-c()
for(i in 1:length(first)){
y <- paste(first, second, sep = "\n")
z <- paste(y, third, sep = "\n")
}
I got out put
[1] "A\n1\na" "B\n2\nb" "C\n3\nc" "D\n4\nd"
[5] "E\n5\ne" "F\n6\nf" "G\n7\ng" "H\n8\nh"
[9] "I\n9\ni"
This is not give me a newline. The format of my colnames(data) for report need to be like that. Thanks for advance.
Am I understanding you correctly that you are looking for this:
first <- LETTERS[1:9]
second <- c(1:9)
third <- letters[1:9]
cat(c(first, "\n", second, "\n", third))
A B C D E F G H I
1 2 3 4 5 6 7 8 9
a b c d e f g h i
?
EDIT:
Will this solve your problem?
Printing R data frame with column names in multiple lines
Related
I want to extract the 3rd element of the second vector of the first
sub-list.....
This is the list of vectors
A <- letters[1:4]
B <- letters[5:10]
C <- letters[11:15]
D <- c(1:10)
E <- c(20:5)
Z <- list(x = c(A,B,C), y = c(D, E))
which returns
>Z
$x
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o"
$y
[1] 1 2 3 4 5 6 7 8 9 10 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5
I've tried this
Z[[1]][B[3]]
but it returns
[1] NA
Thank you in advance
There is no way to differentiate between A, B and C when you use them in a vector (c(A, B, C)). I think the elements in x and y should be in a list :
Z <- list(x = list(A,B,C), y = list(D, E))
If you have that we can do :
Z[[1]][[2]][3]
#[1] "g"
This will return 3rd element of the second vector of the first sub-list.
On lists, you have these two options, for example, extract the second value, of the first element of your list. The first system is only valid, when you give names to the elements of your list.
Z$x[2]
Z[[1]][2]
I have data with 'from' and 'to' columns:
df = data.frame(from = c('A','A','X','E','B','W','C','Y'),
to = c('B','E','Y','C','A','X','A','W'))
I'd like to identify all sequences of 'from-to', considering two or more rows, which starts and ends on the same value. An easy one would be A-B-A:
# df
# from to
# 1 A B # 1. From A to B
# 2 A E
# 3 X Y
# 4 E C
# 5 B A # 2. From B and back to the starting point A, completing the sequence A-B-A
# 6 W X
# 7 C A
# 8 Y W
Another one:
# df
# from to
# 1 A B
# 2 A E # 1.
# 3 X Y
# 4 E C # 2.
# 5 B A
# 6 W X
# 7 C A # 3. -> Thus: A - E - C - A
# 8 Y W
There is also e.g. X - Y - W - X
How can I find such cycles?
Here is another option:
library(igraph)
g <- graph_from_data_frame(h)
#https://lists.nongnu.org/archive/html/igraph-help/2009-04/msg00125.html
find.cycles <- function(graph, k) {
ring <- graph.ring(k, TRUE)
subgraph_isomorphisms(ring, graph)
}
#find all cycles
N <- length(unique(unlist(h)))
l <- unlist(lapply(1L:N, find.cycles, graph=g), recursive=FALSE)
#extract the vertices in each cycle
Filter(Negate(is.null), lapply(l, function(e) {
if (length(e) > 1L) {
nm <- names(e)
c(nm, nm[1L])
}
}))
output:
[[1]]
[1] "A" "B" "A"
[[2]]
[1] "B" "A" "B"
[[3]]
[1] "A" "E" "C" "A"
[[4]]
[1] "X" "Y" "W" "X"
[[5]]
[1] "E" "C" "A" "E"
[[6]]
[1] "W" "X" "Y" "W"
[[7]]
[1] "C" "A" "E" "C"
[[8]]
[1] "Y" "W" "X" "Y"
Reference:
Re: [igraph] Help - find cycles by Gábor Csárdi
I tried to create an easier way to refer to columns with the function below, by allowing both indexes and names. See also link.
So this one works:
df <- data.table::fread("a b c d e f g h i j
1 2 3 4 5 6 7 8 9 10",
header = TRUE)
columns <- c(1:8, "i", 9, "j")
col2num <- function(df, columns){
nums <- as.numeric(columns)
nums[is.na(nums)] <- which(names(df)==columns[is.na(nums)])
return(nums)
}
col2num(df, columns)
#> Warning in col2num(df, columns): NAs introduced by coercion
#> [1] 1 2 3 4 5 6 7 8 9 9 10
And this one works too:
col2name <- function(df, columns){
nums <- as.numeric(columns)
nums[is.na(nums)] <- which(names(df)==columns[is.na(nums)])
return(names(df)[nums])
}
col2name(df, columns)
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "i" "j"
Warning message:
In col2name(df, columns) : NAs introduced by coercion
But when I do the following, it no longer works:
columns <- c(1:7, "j", 8, "i")
col2name <- function(df, columns){
nums <- as.numeric(columns)
nums[is.na(nums)] <- which(names(df)==columns[is.na(nums)])
return(names(df)[nums])
}
col2name(df, columns)
Error in nums[is.na(nums)] <- which(names(df) == columns[is.na(nums)]) :
replacement has length zero
Also, this one does not work:
columns <- c("a", "j", 8, "i")
col2name <- function(df, columns){
nums <- as.numeric(columns)
nums[is.na(nums)] <- which(names(df)==columns[is.na(nums)])
return(names(df)[nums])
}
col2name(df, columns)
[1] "a" "i" "h" "a"
How can I fix this?
We just need to loop over the columns:
col2num <- function(df, columns){
nums <- as.numeric(columns)
nums[is.na(nums)] <- sapply(columns[is.na(as.numeric(columns))],
function(x) which(names(df) == x))
return(nums)
}
col2name <- function(df, columns){
nums <- as.numeric(columns)
nums[is.na(nums)] <- sapply(columns[is.na(as.numeric(columns))],
function(x) which(names(df) == x))
return(names(df)[nums])
}
columns1 <- c(1:8, "i", 9, "j")
columns2 <- c(1:7, "j", 8, "i")
suppressWarnings(col2name(df, columns1))
#> [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "i" "j"
suppressWarnings(col2num(df, columns1))
#> [1] 1 2 3 4 5 6 7 8 9 9 10
suppressWarnings(col2num(df, columns2))
#> [1] 1 2 3 4 5 6 7 10 8 9
suppressWarnings(col2name(df, columns2))
#> [1] "a" "b" "c" "d" "e" "f" "g" "j" "h" "i"
I am using suppressWarnings to avoid getting following warning each time I run the function:
Warning messages:
1: In col2name(df, columns) : NAs introduced by coercion
2: In lapply(X = X, FUN = FUN, ...) : NAs introduced by coercion
An alternative with the disadvantage of necessitating that the data be a data.frame object:
indexr<- function(df, cols){
to_match<-cols[grep("[A-za-z]",cols)]
matched<-match(to_match,names(df))
numerics <- as.numeric(c(setdiff(cols,to_match),matched))
df[c(numerics)]
}
indexr(iris,c(1,"Sepal.Width"))
Sepal.Length Sepal.Width
1 5.1 3.5
2 4.9 3.0
3 4.7 3.2
With your data(drawback is that we go back to a data.frame). Might define a method for that.
data.table::setDF(df)
indexr(df,columns)
a b c d e f g h i i.1 j
1 1 2 3 4 5 6 7 8 9 9 10
Edit To return names instead:
indexr<- function(df, cols){
to_match<-cols[grep("[A-za-z]",cols)]
matched<-match(to_match,names(df))
numerics <- as.numeric(c(setdiff(cols,to_match),matched))
names(df[c(numerics)])
}
indexr(mtcars,c("mpg",5))
[1] "drat" "mpg"
indexr(df,columns)
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "i.1"
[11] "j"
I have a list of vectors, j, that looks like this:
>j
[[1]
[1] "a" "b" "c"
[[2]]
[1] "c" "c"
[[3]]
[1] "d" "d" "d" "a" "a"
.
.
.
I would like to transform this into a dataframe that has one column with each vectors contents concatenated together. So the column would look like:
Column_Name
1 a b c
2 c c
3 d d d a a
I have tried using Replace() function as well as a loop where I would use after:
for (x in 1:length(j)){
j[x] = paste(j[x], collapse = " ")
}
j <- data.frame(matrix(unlist(j), nrow=length(j), byrow=T)
Any guidance would be greatly appreciated.
Thank you.
As you have tried yourself, the sapply function together with the collapse argument of paste should do it all wrapped into a data.frame:
# Toy data
set.seed(1)
j <- replicate(5, rep(sample(letters, 1), sample(1:10,1)))
print(j)
#[[1]]
#[1] "g" "g" "g" "g"
#
#[[2]]
# [1] "o" "o" "o" "o" "o" "o" "o" "o" "o" "o"
#
#[[3]]
#[1] "f" "f" "f" "f" "f" "f" "f" "f" "f"
#
#[[4]]
#[1] "y" "y" "y" "y" "y" "y" "y"
#
#[[5]]
#[1] "q"
# Collapse each element and wrap into a data.frame
res <- data.frame("Column_name" = sapply(j, paste, collapse = " "))
print(res)
# Column_name
#1 g g g g
#2 o o o o o o o o o o
#3 f f f f f f f f f
#4 y y y y y y y
#5 q
The sapply applies the paste-function on each element of the list to create a character vector of the concatenated list elements. The data.frame constructor simply converts that output to the wanted output.
Once provide the name to list and then use stack to convert list in a data.frame. Finally, dplyr package is used to collapse vector from common element separated by .
Sample Data is taken from #AndersEllernBilgrau's answer.
set.seed(1)
j <- replicate(5, rep(sample(letters, 1), sample(1:10,1)))
names(j) <- seq_along(j)
library(dplyr)
stack(j) %>% group_by(ind) %>%
summarise(Column_Name = paste0(values, collapse = " ")) %>%
ungroup() %>% select(-ind)
# # A tibble: 5 x 1
# Column_Name
# <chr>
# 1 g g g g
# 2 o o o o o o o o o o
# 3 f f f f f f f f f
# 4 y y y y y y y
# 5 q
#
I have 2 tables as below:
a = read.table(text=' a b
1 c
1 d
2 c
2 a
2 b
3 a
', head=T)
b = read.table(text=' a c
1 x i
2 y j
3 z k
', head=T)
And I want result to be like this:
1 x i c d
2 y j c a b
3 z k a
Originally I thought to use tapply to transform them to lists (eg. aa = tapply(a[,2], a[,1], function(x) paste(x,collapse=","))), then append it back to table b, but I got stuck...
Any suggestion to do this?
Thanks a million.
One way to do it:
mapply(FUN = c,
lapply(split(b, row.names(b)), function(x) as.character(unlist(x, use.names = FALSE))),
split(as.character(a$b), a$a),
SIMPLIFY = FALSE)
# $`1`
# [1] "x" "i" "c" "d"
#
# $`2`
# [1] "y" "j" "c" "a" "b"
#
# $`3`
# [1] "z" "k" "a"