I have a list of data. In this list, it is either datatable or dataframe. After this problem, I'll bind the list.
Data example:
players $`0001playeraway` key NO MIN 2PTM 2PTA 2PT(%) 3PTM 3PTA 3PT(%) FGM FGA FG(%) FTM FTA FT(%) OR DR REB AST TO STL BS PF 1: * 17 40:00:00 9 15 60 0 0 0 9 15 60 2 4 50 1 8 9 2 4 1 2 1 2: * 16 40:00:00 4 8 50 8 13 62 12 21 57 20 22 91 2 3 5 4 4 0 0 3 3: * 10 33:02:00 2 4 50 0 3 0 2 7 29 0 0 0 0 4 4 1 3 1 0 4 4: * 3 27:46:00 2 3 67 0 0 0 2 3 67 6 6 100 1 4 5 0 1 4 0 3 5: 1 26:24:00 1 1 100 0 2 0 1 3 33 1 2 50 1 0 1 1 0 1 0 4 $`0102playeraway` key NO MIN 2PTM 2PTA 2PT(%) 3PTM 3PTA 3PT(%) FGM FGA FG(%) FTM FTA FT(%) OR DR REB AST TO STL BS PF 1: * 9 40:00:00 1 3 33 2 7 29 3 10 30 3 4 75 1 4 5 8 1 4 1 3 2: * 53 38:18:00 6 14 43 0 0 0 6 14 43 6 8 75 5 3 8 3 4 0 2 5 3: * 13 35:16:00 3 8 38 1 2 50 4 10 40 2 5 40 1 3 4 5 0 0 0 5 4: * 23 31:42:00 2 7 29 2 8 25 4 15 27 7 7 100 1 7 8 1 1 0 0 2 5: 14 22:08 2 3 67 2 4 50 4 7 57 0 0 0 0 2 2 2 1 0 0 1
The rest is omitted.
How I can assign a value to the data table name in the list?
Desired Output:
players $`0001playeraway` year key NO MIN 2PTM 2PTA 2PT(%) 3PTM 3PTA 3PT(%) FGM FGA FG(%) FTM FTA FT(%) OR DR REB AST TO STL BS PF 1: 0001 * 17 40:00:00 9 15 60 0 0 0 9 15 60 2 4 50 1 8 9 2 4 1 2 1 2: 0001 * 16 40:00:00 4 8 50 8 13 62 12 21 57 20 22 91 2 3 5 4 4 0 0 3 3: 0001 * 10 33:02:00 2 4 50 0 3 0 2 7 29 0 0 0 0 4 4 1 3 1 0 4 4: 0001 * 3 27:46:00 2 3 67 0 0 0 2 3 67 6 6 100 1 4 5 0 1 4 0 3 5: 0001 1 26:24:00 1 1 100 0 2 0 1 3 33 1 2 50 1 0 1 1 0 1 0 4 $`0102playeraway` year key NO MIN 2PTM 2PTA 2PT(%) 3PTM 3PTA 3PT(%) FGM FGA FG(%) FTM FTA FT(%) OR DR REB AST TO STL BS PF 1: 0102 * 9 40:00:00 1 3 33 2 7 29 3 10 30 3 4 75 1 4 5 8 1 4 1 3 2: 0102 * 53 38:18:00 6 14 43 0 0 0 6 14 43 6 8 75 5 3 8 3 4 0 2 5 3: 0102 * 13 35:16:00 3 8 38 1 2 50 4 10 40 2 5 40 1 3 4 5 0 0 0 5 4: 0102 * 23 31:42:00 2 7 29 2 8 25 4 15 27 7 7 100 1 7 8 1 1 0 0 2 5: 0102 14 22:08 2 3 67 2 4 50 4 7 57 0 0 0 0 2 2 2 1 0 0 1
score:0
You could do this in a simple Map
with substr
; no need for additional packages.
L
shall serve as an example of a mixed list of data.frame
s and data.table
s:
L
# $`0001playeraway`
# X1 X2 X3 X4
# 1 1 4 7 10
# 2 2 5 8 11
# 3 3 6 9 12
#
# $`0102playeraway`
# X1 X2 X3 X4
# 1 1 4 7 10
# 2 2 5 8 11
# 3 3 6 9 12
#
# $`1003playeraway`
# X1 X2 X3 X4
# 1: 1 4 7 10
# 2: 2 5 8 11
# 3: 3 6 9 12
Method:
library(data.table)
dat <- do.call(rbind, Map(function(x) cbind(year=substr(names(L)[x], 1, 4), L[[x]]), seq(L)))
dat
# year X1 X2 X3 X4
# 1: 0001 1 4 7 10
# 2: 0001 2 5 8 11
# 3: 0001 3 6 9 12
# 4: 0102 1 4 7 10
# 5: 0102 2 5 8 11
# 6: 0102 3 6 9 12
# 7: 1003 1 4 7 10
# 8: 1003 2 5 8 11
# 9: 1003 3 6 9 12
Since data.table
dominates the process, do dat <- as.data.frame(dat)
if you want a data.frame
after.
Data
L <- list(`0001playeraway` = structure(list(X1 = 1:3, X2 = 4:6, X3 = 7:9,
X4 = 10:12), class = "data.frame", row.names = c(NA, -3L)),
`0102playeraway` = structure(list(X1 = 1:3, X2 = 4:6, X3 = 7:9,
X4 = 10:12), class = "data.frame", row.names = c(NA,
-3L)), `1003playeraway` = structure(list(X1 = 1:3, X2 = 4:6,
X3 = 7:9, X4 = 10:12), class = c("data.table", "data.frame"
), row.names = c(NA, -3L)))
score:0
Since you're planning to bind the dataframes anyway, you could skip a step or two by using dplyr
's bind_rows
with the argument .id = "year"
to include the list element names as new variable year
. Using data:
library(data.table)
players <- list(`0001playeraway` = data.table(NO = 1:5),
`0102playeraway` = data.table(NO = 6:10)
)
You can do this:
library(dplyr)
bind_rows(players, .id = "year")
Which returns:
year NO
1 0001playeraway 1
2 0001playeraway 2
3 0001playeraway 3
4 0001playeraway 4
5 0001playeraway 5
6 0102playeraway 6
7 0102playeraway 7
8 0102playeraway 8
9 0102playeraway 9
10 0102playeraway 10
If you really just want the numbers, you could use something like df$year <- sub("(\\d+).*", "\\1", df$year)
, or just pipe the output from bind_rows
into mutate
, e.g.:
bind_rows(players, .id = "year") %>%
mutate(year = sub("(\\d+).*", "\\1", year))
Which returns:
year NO
1 0001 1
2 0001 2
3 0001 3
4 0001 4
5 0001 5
6 0102 6
7 0102 7
8 0102 8
9 0102 9
10 0102 10
Note that this returns a data.frame
. If you need a data.table
just pipe the output from mutate
into as.data.table
.
score:3
You can use purrr::imap
and dplyr::mutate
to add a column to all of the dataframes in the list with the name of each of element. Here, I am also using sringr::str_extract
to get the numeric part of the names as desired.
#some data to work with as an example:
df1 <- data.frame(x = 1:3, y=letters[1:3])
listdfs <- list("tr088text" = df1,"character963" = df1,"00123string" = df1)
library(tidyverse)
imap(listdfs, ~mutate(year = str_extract(.y, "\\-*\\d+\\.*\\d*") , .x))
#> $tr088text
#> x y year
#> 1 1 a 088
#> 2 2 b 088
#> 3 3 c 088
#>
#> $character963
#> x y year
#> 1 1 a 963
#> 2 2 b 963
#> 3 3 c 963
#>
#> $`00123string`
#> x y year
#> 1 1 a 00123
#> 2 2 b 00123
#> 3 3 c 00123
Created on 2019-06-15 by the reprex package (v0.3.0)
Credit To: stackoverflow.com