У меня есть data.frame, созданный из других функций, которые берут список файлов .xlsx и считывают все книги и включенные листы.
Результатом является хороший фрейм данных как таковой:
df<-data.frame(
file.name <-c(“C:/R/Folder1/WB1.xlsx”,
“C:/R/Folder1/WB2.xlsx,”,”C:/R/Folder1/WB2.xlsx”, “C:/R/Folder2/WB1.xlsx”, “C:/R/Folder2/WB1.xls”),
data<-list(df1,df2,df3,df4,df5))
Хотя я могу получить (отключить) кадры данных, я теряю соответствующее местоположение файла, которое мне нужно.
Есть ли способ сохранить соответствующую строку из фрейма данных и вставить () в качестве столбца при удалении?
*Извините за опечатки. Опубликовано в приложении SO.
Updating (now that I am in front of a PC)
Воспроизводимый пример:
данные:
df1<-data.frame(V1=c(sample(900:970,6)),
V2=c(sample(LETTERS[1:6],6)))
df2<-data.frame(V1=sample(750:780,6),
V2=sample(LETTERS[8:16],6))
df3<-data.frame(V1=sample(200:250,6),
V2=sample(LETTERS[10:20],6),
V3=sample(2300:5821,6))
df4<-data.frame(V1=sample(396:480,6),
V2=sample(LETTERS,6))
df5<-data.frame(V1=sample(50:100,6),
V2=sample(LETTERS,6))
df6<-data.frame(V1=sample(200:250,6),
V2=sample(LETTERS,6),
V3=sample(letters,6))
my.list <- list(df1,df2,df3,df4,df5,df6)
mydf<-data.frame(
files=c("C:/Folder1/Data/File1.xlsx","C:/Folder1/Data/File2.xlsx",
"C:/Folder1/Data/File3.xlsx","C:/Folder2/Data/File1.xlsx",
"C:/Folder2/Data/File2.xlsx","C:/Folder2/Data/File3.xlsx"))
mydf$data<-my.list
При попытке разложить - я столкнулся со следующей проблемой (из-за различий в наблюдениях и переменных в списке data.frames (столбец 2):
y<-unnest(mydf, data)
Error: Column `V3` can't be converted from integer to factor
In addition: Warning messages:
1: In bind_rows_(x, .id) : Unequal factor levels: coercing to character
2: In bind_rows_(x, .id) :
binding character and factor vector, coercing into character vector
3: In bind_rows_(x, .id) :
binding character and factor vector, coercing into character vector...
Results from other functions
#tidyverse
y<-mydf %>% unnest(data)
Error: Column `V3` can't be converted from integer to factor
In addition: Warning messages:
1: In bind_rows_(x, .id) : Unequal factor levels: coercing to character
y<-mydf %>%
+ unnest(data) %>%
+ group_by(files) %>%
+ mutate(
+ data = flatten_chr(data),
+ data_colname = str_c("data_", row_number())
+ ) %>% # or just as.character
+ spread(data_colname, data)
Error: Column `V3` can't be converted from integer to factor
In addition: Warning messages:
1: In bind_rows_(x, .id) : Unequal factor levels: coercing to character
Adding utilized function to pull .xlsx and all sheets in - as seen in this example:
library(tidyverse)
library(readxl)
dir_path1 <- "~/File1/Data/Qtr1"
dir_path2 <- "~/File1/Data/Qtr2"
dir_path3 <- "~/File1/Data/Qtr3"
dir_path4 <- "~/File1/Data/Qtr4"
re_file <- ".xlsx"
read_sheets <- function(dir_path1, file){
xlsx_file <- paste0(dir_path1, file)
xlsx_file %>%
excel_sheets() %>%
set_names() %>%
map_df(read_excel, path = xlsx_file, .id = 'sheet_name') %>%
mutate(file_name = file) %>%
select(file_name, sheet_name, everything())
}
df <- list.files(dir_path, re_file) %>%
map_df(~ read_sheets(dir_path, .))
Возвращает:
# A tibble: 15 x 5
file_name sheet_name col1
<chr> <chr> <dbl>
1 Q1_File1.xlsx Sheet1 1
2 Q1_File1.xlsx Sheet2 1
3 Q1_File2.xlsx Sheet1 1
...
Однако, в отличие от демонстрационных данных (как показано в ссылке), возвращаемые данные (col1) представляют собой список фреймов данных.
Проблема связана с тем, что df3 имеет числовое значение для V3
, а df6 — это символ для V3
. Ты сможешь:
df3$V3
или df6$V3
Кроме того, чтобы избавиться от предупреждений, вы можете создать свои кадры данных с помощью stringsAsFactors = FALSE
или использовать tibble()
вместо data.frame()
, поскольку это поведение по умолчанию для таблички.
Редактировать:, чтобы лучше выполнить вариант 2, вы можете использовать приведенный ниже код, чтобы добавить префикс к каждой переменной.
my.list2 <- lapply(my.list, function(x) sapply(x, function(y) paste0(class(y), names(y))))
, function(x)
{
x%>%
rename_if (is.numeric, ~paste0('num', .x))%>%
rename_if (is.character, ~paste0('char', .x))%>%
rename_if (is.factor, ~paste0('fact', .x))
}
)
Это вариант 2, и он работает только с факторными предупреждениями:
df1<-data.frame(V1=c(sample(900:970,6)),
V2=c(sample(LETTERS[1:6],6)))
df2<-data.frame(V1=sample(750:780,6),
V2=sample(LETTERS[8:16],6))
df3<-data.frame(V1=sample(200:250,6),
V2=sample(LETTERS[10:20],6),
V4=sample(2300:5821,6)) #used to be V3
df4<-data.frame(V1=sample(396:480,6),
V2=sample(LETTERS,6))
df5<-data.frame(V1=sample(50:100,6),
V2=sample(LETTERS,6))
df6<-data.frame(V1=sample(200:250,6),
V2=sample(LETTERS,6),
V3=sample(letters,6))
my.list <- list(df1,df2,df3,df4,df5,df6)
mydf<-data.frame(
files=c("C:/Folder1/Data/File1.xlsx","C:/Folder1/Data/File2.xlsx",
"C:/Folder1/Data/File3.xlsx","C:/Folder2/Data/File1.xlsx",
"C:/Folder2/Data/File2.xlsx","C:/Folder2/Data/File3.xlsx"))
mydf$data<-my.list
unnest(mydf, data)
files V1 V2 V4 V3
1 C:/Folder1/Data/File1.xlsx 951 A NA <NA>
2 C:/Folder1/Data/File1.xlsx 932 F NA <NA>
3 C:/Folder1/Data/File1.xlsx 908 B NA <NA>
4 C:/Folder1/Data/File1.xlsx 953 C NA <NA>
5 C:/Folder1/Data/File1.xlsx 929 E NA <NA>
6 C:/Folder1/Data/File1.xlsx 928 D NA <NA>
7 C:/Folder1/Data/File2.xlsx 778 K NA <NA>
8 C:/Folder1/Data/File2.xlsx 771 H NA <NA>
9 C:/Folder1/Data/File2.xlsx 757 M NA <NA>
10 C:/Folder1/Data/File2.xlsx 773 P NA <NA>
11 C:/Folder1/Data/File2.xlsx 759 N NA <NA>
12 C:/Folder1/Data/File2.xlsx 765 O NA <NA>
13 C:/Folder1/Data/File3.xlsx 236 M 3964 <NA>
14 C:/Folder1/Data/File3.xlsx 214 O 5241 <NA>
...truncated
Хм, проблема здесь в том, что файлы .xlsx считываются - я имею в виду, много. У кого-то 50, у кого-то 300. И имена у них одинаковые. Любая идея, как я могу преодолеть это? Я собираюсь вставить пример функции, которую я использую для чтения файлов, в
Это может быть другой вопрос. Но нельзя ли импортировать таблицу с заголовками? В противном случае, как вы могли бы действительно ссылаться на поля вниз по дороге?
Смотрите комментарий. Вы все равно должны задать другой вопрос, если хотите получить лучший ответ на часть переименования переменных на основе класса.
привет @Коул. У меня есть решение - я верю. Я собираюсь опубликовать это здесь на всякий случай, если у кого-то будет такая же проблема,
Возможно, посмотрите функцию unnest в пакете tidyr (см. примеры tidyr.tidyverse.org/reference/unnest.html)