Using lapply to group list of data frames by column - r

I have a list that contains multiple data frames. I would like to sort the data by Category (A) and sum the Frequencies (B) using the lapply-command.
The data is df_list
df_list
$`df.1`
A B
1 Apples 2
2 Pears 5
3 Apples 6
4 Pears 1
5 Apples 3
$`df.2`
A B
1 Oranges 2
2 Pineapples 5
3 Oranges 6
4 Pineapples 1
5 Oranges 3
The desired outcome df_list_2 looks like this:
df_list_2
$`df.1`
A B
1 Apples 11
2 Pears 6
$`df.2`
A B
1 Oranges 11
2 Pineapples 6
I have tried the following code based on lapply:
df_list_2<-df_list[, lapply(B, sum), by = A]
However, I get an error code, saying that A was not found.
Either I mistake how the lapply command works in this case or my understating of how it should work is flawed.
Any help much appreciated.

You need to aggregate in lapply
lapply(df_list, function(x) aggregate(B~A, x, sum))
#[[1]]
# A B
#1 Apples 11
#2 Pears 6
#[[2]]
# A B
#1 Oranges 11
#2 Pineapples 6
Using map from purrr and dplyr it would be
library(dplyr)
purrr::map(df_list, ~.x %>% group_by(A) %>% summarise(sum = sum(B)))
data
df_list <- list(structure(list(A = structure(c(1L, 2L, 1L, 2L, 1L),
.Label = c("Apples", "Pears"), class = "factor"), B = c(2L, 5L, 6L, 1L, 3L)),
class = "data.frame", row.names = c("1", "2", "3", "4", "5")),
structure(list(A = structure(c(1L, 2L, 1L, 2L, 1L), .Label = c("Oranges",
"Pineapples"), class = "factor"), B = c(2L, 5L, 6L, 1L, 3L)), class = "data.frame",
row.names = c("1", "2", "3", "4", "5")))

I fear you might not have a clear idea of lapply nor the extract operator ([). Remember lapply(list, function) applies the specified function you give it to each element of the list you give it. Extract gives you the element you specify:
x <- c('a', 'b', 'c')
x[2]
## "b"
I would imagine that somewhere in your R workspace you have an object names B which is why you didn't get an error along the lines of
## Error in lapply(B, sum) : object 'B' not found
Conversely if you had (accidentally or intentionally) defined both A and B you would see the error
## Error in df_list[, lapply(B, sum), by = A] : incorrect number of dimensions
because that's not at all how to use [; remember, you just pass indexes or booleans to [ along with the occasional optional argument, but by is not one of those.
So without further adieu, here's how I would do this (in base R):
# make some data
a <- c(1, 2, 1, 2, 1)
b <- c(2, 5, 6, 1, 3)
df_list <- list(df.1 = data.frame(A = c('Apples', 'Pears')[a], B = b),
df.2 = data.frame(A = c('Oranges', 'Pineapples')[a], B = b))
# simplify it
df_list_2 <- lapply(df_list, function(x) {
aggregate(list(B = x$B), list(A = x$A), sum)
})
# the desired result
df_list_2
## $df.1
## A B
## 1 Apples 11
## 2 Pears 6
##
## $df.2
## A B
## 1 Oranges 11
## 2 Pineapples 6
You can take advantage of the fact that a data.frame is just a list and shorten up your code like this:
df_list_2 <- lapply(df_list, function(x) {
aggregate(x['B'], x['A'], sum)
})
but the first way of writing it should help make more clear what we're doing

The data.table syntax in OP's post can changed to
library(data.table)
lapply(df_list, function(x) as.data.table(x)[, .(B = sum(B)), by = A])
#$df.1
# A B
#1: Apples 11
#2: Pears 6
#$df.2
# A B
#1: Oranges 11
#2: Pineapples 6
data
df_list <- list(df.1 = structure(list(A = structure(c(1L, 2L, 1L, 2L, 1L
), .Label = c("Apples", "Pears"), class = "factor"), B = c(2L,
5L, 6L, 1L, 3L)), class = "data.frame", row.names = c("1", "2",
"3", "4", "5")), df.2 = structure(list(A = structure(c(1L, 2L,
1L, 2L, 1L), .Label = c("Oranges", "Pineapples"), class = "factor"),
B = c(2L, 5L, 6L, 1L, 3L)), class = "data.frame", row.names = c("1",
"2", "3", "4", "5")))

Related

Normalizing matched data in R

Consider:
Pair X
1 2
1 3
2 1
2 2
If I have a dataframe that is structured like the example above, how do I normalize column X given the Pair column?
In other words, the two elements should be translated to 0.4 (2/(2+3)) and 0.6 (3/(2+3)) for Pair 1 and .333 (1/(1+2)) and .666 (2/(1+2)) for Pair 2.
We can use base R
df$norm <- with(df, X/rowsum(X, Pair)[Pair])
df$norm
#[1] 0.4000000 0.6000000 0.3333333 0.6666667
data
df <- structure(list(Pair = c(1L, 1L, 2L, 2L), X = c(2L, 3L, 1L, 2L
)), class = "data.frame", row.names = c(NA, -4L))
You can do this in base R:
df$norm <- with(df, X/ave(X, Pair, FUN = sum))
df
# Pair X norm
#1 1 2 0.40
#2 1 3 0.60
#3 2 1 0.33
#4 2 2 0.67
dplyr
library(dplyr)
df %>% group_by(Pair) %>% mutate(norm = X/sum(X))
and data.table:
library(data.table)
setDT(df)[, norm := X/sum(X), Pair]
data
df <- structure(list(Pair = c(1L, 1L, 2L, 2L), X = c(2L, 3L, 1L, 2L
)), class = "data.frame", row.names = c(NA, -4L))

Multiple aggregation with unspecified FUN in R

I have a data.frame object in R and need to:
Group by col_1
Select rows from col_3 such that col_2 value is the second largest one (if there is only observation for the given value of col_1, return 'NA' for instance).
How can I obtain this?
Example:
scored xg first_goal scored_mane
1 1 1.03212 Lallana 0
2 1 2.06000 Mane 1
3 2 2.38824 Robertson 1
4 2 1.64291 Mane 1
Group by "scored_mane", return values from "scored" where "xg" is the second largest. Expected output: "NA", 1
You can try the following base R solution, using aggregate + merge
res <- merge(aggregate(xg~scored_mane,df,function(v) sort(v,decreasing = T)[2]),df,all.x = TRUE)[,"scored"]
such that
> res
[1] NA 1
DATA
structure(list(scored = c(1L, 1L, 2L, 2L), xg = c(1.03212, 2.06,
2.38824, 1.64291), first_goal = c("Lallana", "Mane", "Robertson",
"Mane"), scored_mane = c(0L, 1L, 1L, 1L)), class = "data.frame", row.names = c("1",
"2", "3", "4")) -> df

How to loop through a list of lists, whilst subsetting the lists based on a variable

I have a list of lists similar to the toy example given here. I would like to loop through this list to return a new list which has had elements removed based on a variable.
dput(head(list)):
list(FEB_gems = list(GAME1 = structure(list(GAME1_Class = structure(c(2L,
1L, 5L, 4L, 3L), .Label = c("fighter", "paladin", "rouge", "sorcerer",
"wizard"), class = "factor"), GAME1_Race = structure(c(3L, 1L,
4L, 3L, 2L), .Label = c("elf", "gnome", "human", "orc"), class = "factor"),
GAME1_Alignment = structure(c(4L, 2L, 1L, 5L, 3L), .Label = c("CE",
"CG", "LG", "NE", "NN"), class = "factor"), GAME1_Level = c(6,
7, 6, 7, 7), GAME1_Alive = structure(c(1L, 1L, 1L, 1L, 1L
), .Label = "y", class = "factor")), class = "data.frame", row.names = c(NA,
-5L)), GAME2 = structure(list(GAME2_Class = structure(c(3L, 5L,
2L, 4L, 1L), .Label = c("bard", "cleric", "fighter", "monk",
"wizard"), class = "factor"), GAME2_Race = structure(c(2L, 3L,
2L, 4L, 1L), .Label = c("dwarf", "elf", "half-elf", "human"), class = "factor"),
GAME2_Alignment = structure(c(4L, 2L, 1L, 5L, 3L), .Label = c("CE",
"CG", "LG", "NE", "NN"), class = "factor"), GAME2_Level = c(5,
5, 5, 5, 5), GAME2_Alive = structure(c(1L, 2L, 2L, 2L, 2L
), .Label = c("n", "y"), class = "factor")), class = "data.frame", row.names = c(NA,
-5L))), MAR_gems = list(GAME3 = structure(list(GAME3_Class = structure(c(2L,
1L, 5L, 4L, 3L), .Label = c("barbarian", "cleric", "monk", "ranger",
"warlock"), class = "factor"), GAME3_Race = structure(c(2L, 3L,
2L, 4L, 1L), .Label = c("dwarf", "elf", "half-elf", "human"), class = "factor"),
GAME3_Alignment = structure(c(2L, 2L, 1L, 3L, 2L), .Label = c("CE",
"LG", "LN"), class = "factor"), GAME3_Level = c(1, 1, 1,
1, 1), GAME3_Alive = structure(c(2L, 2L, 2L, 1L, 2L), .Label = c("n",
"y"), class = "factor")), class = "data.frame", row.names = c(NA,
-5L)), GAME4 = structure(list(GAME4_Class = structure(c(2L, 1L,
5L, 4L, 3L), .Label = c("fighter", "paladin", "rouge", "sorcerer",
"wizard"), class = "factor"), GAME4_Race = structure(c(2L, 3L,
2L, 4L, 1L), .Label = c("dwarf", "elf", "half-elf", "human"), class = "factor"),
GAME4_Alignment = structure(c(1L, 2L, 1L, 4L, 3L), .Label = c("CE",
"CG", "LG", "LN"), class = "factor"), GAME4_Level = c(5,
5, 5, 5, 5), GAME4_Alive = structure(c(1L, 2L, 2L, 2L, 2L
), .Label = c("n", "y"), class = "factor")), class = "data.frame", row.names = c(NA,
-5L))))
I have made some attempt at manually sub-setting the list of lists. A function would be preferable is because I have multiple types of data to subset.
1) sub-setting Level columns based on interger
df1 <- Games.Split[[1]][[1]]
Level <- df1[which(df1[4] > 6),]
Games.Split[[1]][[1]] <- Level
df1:
GAME1_Class GAME1_Race GAME1_Alignment GAME1_Level GAME1_Alive
1 paladin human NE 6 y
2 fighter elf CG 7 y
3 wizard orc CE 6 y
4 sorcerer human NN 7 y
5 rouge gnome LG 7 y
Level:
GAME1_Class GAME1_Race GAME1_Alignment GAME1_Level GAME1_Alive
2 fighter elf CG 7 y
4 sorcerer human NN 7 y
5 rouge gnome LG 7 y
2) sub-setting Alive columns based on string
df2 <- Games.Split[[1]][[2]]
Alive <- df2[which(df2[5] == 'y'),]
Games.Split[[1]][[2]] <- Alive
df2:
GAME2_Class GAME2_Race GAME2_Alignment GAME2_Level GAME2_Alive
1 fighter elf NE 5 n
2 wizard half-elf CG 5 y
3 cleric elf CE 5 y
4 monk human NN 5 y
5 bard dwarf LG 5 y
Alive:
GAME2_Class GAME2_Race GAME2_Alignment GAME2_Level GAME2_Alive
2 wizard half-elf CG 5 y
3 cleric elf CE 5 y
4 monk human NN 5 y
5 bard dwarf LG 5 y
However I'm struggling to put this into action in a for loop to perform these sub-setting tasks on the entire list.
for (i in Games.Split){
for (j in i){
Alive = j[which(j[5] == 'y'),]
j <- Alive
}
}
Overall, a function/ method that can iterate through the whole list to provide a new list which no longer has the removed elements.
Since you have two levels of lists to organizing the dataframes, this will require a nested list apply function (lapply)-- same as a loop but a little neater. Here is an example that creates a function to subset the game list (gameList) based on maximum level (maxLevel):
listSubset <- function(x, maxLevel){
lapply(x, function(ls){
lapply(ls, function(df) df[df[[grep('Level', names(df), value = TRUE)]] < maxLevel, ])
})
}
listSubset(x = gameList, maxLevel = 6)
Output:
$`FEB_gems`
$`FEB_gems`$`GAME1`
[1] GAME1_Class GAME1_Race GAME1_Alignment GAME1_Level GAME1_Alive
<0 rows> (or 0-length row.names)
$`FEB_gems`$GAME2
GAME2_Class GAME2_Race GAME2_Alignment GAME2_Level GAME2_Alive
1 fighter elf NE 5 n
2 wizard half-elf CG 5 y
3 cleric elf CE 5 y
4 monk human NN 5 y
5 bard dwarf LG 5 y
$MAR_gems
$MAR_gems$`GAME3`
GAME3_Class GAME3_Race GAME3_Alignment GAME3_Level GAME3_Alive
1 cleric elf LG 1 y
2 barbarian half-elf LG 1 y
3 warlock elf CE 1 y
4 ranger human LN 1 n
5 monk dwarf LG 1 y
$MAR_gems$GAME4
GAME4_Class GAME4_Race GAME4_Alignment GAME4_Level GAME4_Alive
1 paladin elf CE 5 n
2 fighter half-elf CG 5 y
3 wizard elf CE 5 y
4 sorcerer human LN 5 y
5 rouge dwarf LG 5 y
All the functions are in base R, so no need to install and learn new packages.
If there are only two nested lists, and want different filtering conditions, apply on it individually and assign the output back to the list element. We loop through the master list with map and then apply the logical conditions
library(purrr)
library(dplyr)
lst2 <- map(lst1, ~ {
.x[[1]] <- .x[[1]] %>%
filter_at(4, all_vars(. > 6))
.x[[2]] <- .x[[2]] %>%
filter_at(5, all_vars(. == 'y'))
.x
})
I'd argue that life would be easier if you restructure your data, then use dplyr's filter to pull out what you want (or omit what you don't want). Assuming your original data is called foo:
# Load libraries
library(dplyr)
library(purrr)
# Remove one list
bar <- unlist(foo, recursive = FALSE)
# Get names of campaigns and games
campaign_games <- data.frame(do.call(rbind, strsplit(names(bar), "\\.")))
# Add campaigns and games numbers to data frames
ls_games <- pmap(list(campaign_games[, 1], campaign_games[, 2], bar), cbind)
# Rename all columns
ls_games <- lapply(ls_games, function(x){names(x) <- c("Campaign", "Game_n", "Class", "Race", "Alignment", "Level", "Alive"); x})
# Convert to data frame
df <- bind_rows(ls_games)
# Look at result
head(df)
Now your data looks like this:
# Campaign Game_n Class Race Alignment Level Alive
# 1 FEB_gems GAME1 paladin human NE 6 y
# 2 FEB_gems GAME1 fighter elf CG 7 y
# 3 FEB_gems GAME1 wizard orc CE 6 y
# 4 FEB_gems GAME1 sorcerer human NN 7 y
# 5 FEB_gems GAME1 rouge gnome LG 7 y
# 6 FEB_gems GAME2 fighter elf NE 5 n
which is easy to handle. For example, pull those that are alive in game 1 of FEB gems and are level 7 or higher.
df %>% filter(Alive == "y", Campaign == "FEB_gems",
Level >= 7, Game_n == "GAME1")
# Campaign Game_n Class Race Alignment Level Alive
# 1 FEB_gems GAME1 fighter elf CG 7 y
# 2 FEB_gems GAME1 sorcerer human NN 7 y
# 3 FEB_gems GAME1 rouge gnome LG 7 y

Remove column names in a DataFrame

In sparkR I have a DataFrame data.
When I type head(data) we get this output
C0 C1 C2 C3
1 id user_id foreign_model_id machine_id
2 1 3145 4 12
3 2 4079 1 8
4 3 1174 7 1
5 4 2386 9 9
6 5 5524 1 7
I want to remove C0,C1,C2,C3 because they give me problems later one. For example when I use the filter function:
filter(data,data$machine_id==1)
can't run because of this.
I have read the data like this
data <- read.df(sqlContext, "/home/ole/.../data", "com.databricks.spark.csv")
SparkR made the header into the first row and gave the DataFrame a new header because the default for the header option is "false". Set the header option to header="true" and then you won't have to handle with this problem.
data <- read.df(sqlContext, "/home/ole/.../data", "com.databricks.spark.csv", header="true")
Try
colnames(data) <- unlist(data[1,])
data <- data[-1,]
> data
# id user_id foreign_model_id machine_id
#2 1 3145 4 12
#3 2 4079 1 8
#4 3 1174 7 1
#5 4 2386 9 9
#6 5 5524 1 7
If you wish, you can add rownames(data) <- NULL to correct for the row numbers after the deletion of the first row.
After this manipulation, you can select rows that correspond to certain criteria, like
subset(data, data$machine_id==1)
# id user_id foreign_model_id machine_id
#4 3 1174 7 1
In base R, the function filter() suggested in the OP is part of the stats namespace and is usually reserved for the analysis of time series.
data
data <- structure(list(C0 = structure(c(6L, 1L, 2L, 3L, 4L, 5L),
.Label = c("1", "2", "3", "4", "5", "id"), class = "factor"),
C1 = structure(c(6L, 3L, 4L, 1L, 2L, 5L), .Label = c("1174", "2386",
"3145", "4079", "5524", "user_id"), class = "factor"),
C2 = structure(c(5L, 2L, 1L, 3L, 4L, 1L),
.Label = c("1", "4", "7", "9", "foreign_model_id"), class = "factor"),
C3 = structure(c(6L, 2L, 4L, 1L, 5L, 3L),
.Label = c("1", "12", "7", "8", "9", "machine_id"), class = "factor")),
.Names = c("C0", "C1", "C2", "C3"), class = "data.frame",
row.names = c("1", "2", "3", "4", "5", "6"))
try this
names <- c()
for (i in seq(along = names(data))) {
names <- c(names, toString(data[1,i]))
}
names(data) <- names
data <- data[-1,]
I simply can't use the answers because in sparkR it can't run: object of type 'S4' is not subsettable. I solved the problem this way, however, I think there is a better way to solve it.
data <- withColumnRenamed(data, "C0","id")
data <- withColumnRenamed(data, "C1","user_id")
data <- withColumnRenamed(data, "C2","foreign_model_id")
data <- withColumnRenamed(data, "C3","machine_id")
And now I can successfully use the filter function as I want to.

Counting where the string appears in row with caveat - [R]

I have a dataset where the first three columns (G1P1, G1P2, G1P3) indicate one grouping of three individuals (i.e. Sidney, Blake, Max on Row 1), the second three columns (G2P1, G2P2, G2P3) indicate another grouping of three individuals (i.e. David, Steve, Daniel on Row 2), etc.... There are a total of 12 individuals, and dataset is pretty much all the possible groupings of these 12 people (approximately 300,000 rows). Each group's cumulative test scores are represented on far right columns, (G1.Sum, G2.Sum, G3.Sum, G4.Sum
).
#### The dput(data) of the first five rows ####
data <- structure(list(X = 1:5, G1P1 = structure(c(4L, 4L, 4L, 4L, 4L), .Label = c("CHRIS", "DAVID", "EVA", "SIDNEY"), class = "factor"), G1P2 = structure(c(1L, 1L, 1L, 1L, 1L), .Label = c("BLAKE", "NICK", "PATRIC", "STEVE"), class = "factor"), G1P3 = structure(c(4L, 4L, 4L, 4L, 4L), .Label = c("BEAU", "BRANDON", "DANIEL", "MAX"), class = "factor"), G2P1 = structure(c(2L, 2L, 1L, 1L, 3L), .Label = c("CHRIS", "DAVID", "EVA", "SIDNEY"), class = "factor"), G2P2 = structure(c(4L, 4L, 3L, 3L, 2L), .Label = c("BLAKE", "NICK", "PATRIC", "STEVE"), class = "factor"), G2P3 = structure(c(3L, 3L, 2L, 2L, 1L), .Label = c("BEAU", "BRANDON", "DANIEL", "MAX"), class = "factor"), G3P1 = structure(c(1L, 3L, 2L, 3L, 2L), .Label = c("CHRIS", "DAVID", "EVA", "SIDNEY"), class = "factor"), G3P2 = structure(c(3L, 2L, 4L, 2L, 4L), .Label = c("BLAKE", "NICK", "PATRIC", "STEVE"), class = "factor"), G3P3 = structure(c(2L, 1L, 3L, 1L, 3L), .Label = c("BEAU", "BRANDON", "DANIEL", "MAX"), class = "factor"), G4P1 = structure(c(3L, 1L, 3L, 2L, 1L), .Label = c("CHRIS", "DAVID", "EVA", "SIDNEY"), class = "factor"), G4P2 = structure(c(2L, 3L, 2L, 4L, 3L), .Label = c("BLAKE", "NICK", "PATRIC", "STEVE"), class = "factor"), G4P3 = structure(c(1L, 2L, 1L, 3L, 2L), .Label = c("BEAU", "BRANDON", "DANIEL", "MAX"), class = "factor"), G1.Sum = c(63.33333333, 63.33333333, 63.33333333, 63.33333333, 63.33333333), G2.Sum = c(58.78333333, 58.78333333, 54.62333333, 54.62333333, 58.69), G3.Sum = c(54.62333333, 58.69, 58.78333333, 58.69, 58.78333333), G4.Sum = c(58.69, 54.62333333, 58.69, 58.78333333, 54.62333333)), .Names = c("X", "G1P1", "G1P2", "G1P3", "G2P1", "G2P2", "G2P3", "G3P1", "G3P2", "G3P3", "G4P1", "G4P2", "G4P3", "G1.Sum", "G2.Sum", "G3.Sum", "G4.Sum"), row.names = c(NA, 5L), class = "data.frame")
I was wondering how you would write an R function so for each row, you can record where the person's group score ranked. For example, on Row 1, SIDNEY was in a group with the highest score at 63.3333. So his rank would be a '1.' But for BRANDON, his group scored last (54.62333), so her rank would be 4. I would like my final data.frame output to be something like this:
ranks <- t(apply(data[grep("Sum", names(data))], 1, function(x) rep(match(x, sort(x, decreasing=T)),each=3)))
just.names <- data[grep("P", names(data))] #Subset without sums
names <- as.character(unlist(just.names[1,])) #create name vector
sapply(names, function(x) ranks[just.names == x])
# SIDNEY BLAKE MAX DAVID STEVE DANIEL CHRIS PATRIC BRANDON EVA NICK BEAU
# [1,] 1 1 1 2 2 2 4 4 4 3 3 3
# [2,] 1 1 1 2 2 2 4 4 4 3 3 3
# [3,] 1 1 1 2 2 2 4 4 4 3 3 3
# [4,] 1 1 1 2 2 2 4 4 4 3 3 3
# [5,] 1 1 1 2 2 2 4 4 4 3 3 3
We first rank the sums and replicate them 3 times each. Next we subset the larger data frame with the names only (take out the sum columns). We make a vector with the individual names. And lastly, we subset the ranks matrix that we created first by seeing where in the data frame the name appears.
Using dplyr and tidyr. First, ranking, then uniting all the rows with their rank, converting to long data, separating out the variables, then finally spreading.
It got really long, and can probably be simplified:
library(dplyr)
library(tidyr)
data[ ,14:17] <- t(apply(-data[ ,14:17], 1 , rank))
data %>% unite("g1", starts_with("G1")) %>%
unite("g2", starts_with("G2")) %>%
unite("g3", starts_with("G3")) %>%
unite("g4", starts_with("G4")) %>%
gather(Row, val, -X) %>%
select(-Row) %>%
separate(val, c("1", "2", "3", "rank")) %>%
gather(zzz, name, -X, -rank) %>%
select(-zzz) %>%
spread(name, rank)
X BEAU BLAKE BRANDON CHRIS DANIEL DAVID EVA MAX NICK PATRIC SIDNEY STEVE
1 1 3 1 4 4 2 2 3 1 3 4 1 2
2 2 3 1 4 4 2 2 3 1 3 4 1 2
3 3 3 1 4 4 2 2 3 1 3 4 1 2
4 4 3 1 4 4 2 2 3 1 3 4 1 2
5 5 3 1 4 4 2 2 3 1 3 4 1 2
Using previous answer's 'rank' matrix and library(reshape2) to convert wide data.frame to long data.frame,
ranks <- t(apply(test[grep("Sum",names(test))], 1, function (x)
rep(match(x, sort(x, decreasing=T)),each=3)))
colnames(ranks) <- names(test)[grep("P", names(test))]
# data subset
test_L <- test[,-grep("Avg", names(test))]
df_player <- data.frame(position= names(test)[grep("P", names(test))],
t(test_L[,-1]), row.names = NULL)
df_ranks <- data.frame(position=names(test)[grep("P", names(test))],
t(ranks), row.names=NULL)
# Combine two temporary data.frames
df_player_melted <- melt(df_player, id=1,
variable.name = "rowNumber", value.name = "player")
df_ranks_melted <- rank= melt(df_ranks, id=1,
variable.name = "rowNumber", value.name = "rank")
df <- cbind(df_player_melted, rank= df_ranks_melted$rank)
# cast into the output format you want
df <- dcast(df, rowNumber ~ player + rank)[1,]

Resources