如何使用 do.call() 读取特定行?
How can I use do.call() to read specific rows?
我正在使用 do.call() 命令读取 csv 文件列表,以便将所有数据点放在一个 csv 文件中。我一直在使用以下内容:
files = list.files(path = "G:/SafeGraph201708MidWest",
pattern = "*.csv",
recursive = TRUE,
full.names = TRUE)
library(data.table)
DT = do.call(rbind, lapply(files, fread))
我不想读取每个文件中的所有行,而是想读取特定的行。尤其是在这个范围内的:
Data <- filter(DT, longitude >= -86.97 & longitude <= -86.78,
latitude >= 40.35 & latitude <= 40.49)
有没有一种方法可以使用 do.call() 来做到这一点?期待尽快回复。谢谢!
有多种策略可以解决这个问题。您可以使用 lapply
将所有数据导入列表,然后根据您的过滤器从每个列表元素中过滤掉。您将使用 data.table::rbindlist
来生成最终的 data.table。另一种方法是一步完成,例如(显然没有测试)
library(data.table)
files = list.files(path = "G:/SafeGraph201708MidWest",
pattern = "*.csv",
recursive = TRUE,
full.names = TRUE)
xy <- lapply(files, FUN = function(x) {
out <- fread(x)
out <- filter(out, longitude >= -86.97 & longitude <= -86.78,
latitude >= 40.35 & latitude <= 40.49)
out
})
xy <- rbindlist(xy)
假设您使用 Windows PC 并且至少安装了 Microsoft Office 2007+,请考虑使用 JET/ACE SQL 引擎(.dll 文件)直接查询 CSV,这是非常适合 MS Access 的引擎。
下面包括两个使用 Access 或 Excel 的连接字符串。任何一个版本都可以工作,文件确实需要存在,但除了连接到 ACE 之外从未使用过。连接后,将从相同或不同路径查询 CSV 文件。
library(odbc)
# VERIFY AVAILABLE DSNs AND DRIVERS
odbcListDataSources()
# DSN VERSIONS
conn <- dbConnect(odbc::odbc(), DSN ="MS Access Database;DBQ=C:\Path\To\Access.accdb;");
conn <- dbConnect(odbc::odbc(), DSN ="Excel Files;DBQ=C:\Path\To\Excel.xlsx;");
# DRIVER VERSIONS
conn <- dbConnect(odbc::odbc(),
.connection_string = "Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=C:\Path\To\Access.accdb;");
conn <- dbConnect(odbc::odbc(),
.connection_string ="Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};DBQ=C:\Path\To\Excel.xlsx;");
# CSV QUERY
df <- dbGetQuery(conn, "SELECT t.*
FROM [text;database=C:\Path\To\CSV_Folder].Name_of_File.csv AS t
WHERE t.longitude BETWEEN -86.97 AND -86.78
AND t.latitude BETWEEN 40.35 AND 40.49;")
head(df)
dbDisconnect(conn)
循环中:
files = list.files(path = "G:/SafeGraph201708MidWest",
pattern = "*.csv",
recursive = TRUE,
full.names = TRUE)
df_list <- lapply(files, function(f)
df <- dbGetQuery(conn,
paste0("SELECT t.* ",
" FROM [text;database=G:\SafeGraph201708MidWest].", f, " AS t ",
" WHERE t.longitude BETWEEN -86.97 AND -86.78",
" AND t.latitude BETWEEN 40.35 AND 40.49;")
)
)
final_dt <- rbindlist(df_list)
您可以使用 data.table::fread()
中的能力来执行命令并 'read' 结果。
我假设您正在使用 windows,因此您可以在命令提示符中访问 findstr
功能。
因此,如果您可以在要提取的行上构建 'hits' 的正则表达式,则可以在将整个文件读入 R 之前过滤需要的行。这(可能)是一个 huuuge memory-saver 在较大的文件上,可能会大大加快您的工作流程。
示例数据
拉特说 coords.csv 看起来是这样的:
id,latitude,longitude
1,10,11
2,11,12
3,12,13
4,13,14
5,14,15
在此示例中,您要提取纬度在 12 和 14 之间以及经度在 11 和 13 之间的线
代码
#build a list of files (I created only one)
#make sure you use the full path (not relative)
x <- list.files( path = "C:/folder", pattern = "coord.csv", full.names = TRUE )
#build reges that only hits on rows with:
# latitude 12-14
# longitude 11-13
pattern = "^[0-9],1[2-4],1[1-3]$"
#read the file(s), extract the lines with match the regex-pattern
#and bind the resuklt to a data.table
rbindlist( lapply( x, function(x) {
fread( cmd = paste0( "findstr /R ", pattern, " ", x ), header = FALSE )
} ) )
输出
V1 V2 V3
1: 3 12 13
我正在使用 do.call() 命令读取 csv 文件列表,以便将所有数据点放在一个 csv 文件中。我一直在使用以下内容:
files = list.files(path = "G:/SafeGraph201708MidWest",
pattern = "*.csv",
recursive = TRUE,
full.names = TRUE)
library(data.table)
DT = do.call(rbind, lapply(files, fread))
我不想读取每个文件中的所有行,而是想读取特定的行。尤其是在这个范围内的:
Data <- filter(DT, longitude >= -86.97 & longitude <= -86.78,
latitude >= 40.35 & latitude <= 40.49)
有没有一种方法可以使用 do.call() 来做到这一点?期待尽快回复。谢谢!
有多种策略可以解决这个问题。您可以使用 lapply
将所有数据导入列表,然后根据您的过滤器从每个列表元素中过滤掉。您将使用 data.table::rbindlist
来生成最终的 data.table。另一种方法是一步完成,例如(显然没有测试)
library(data.table)
files = list.files(path = "G:/SafeGraph201708MidWest",
pattern = "*.csv",
recursive = TRUE,
full.names = TRUE)
xy <- lapply(files, FUN = function(x) {
out <- fread(x)
out <- filter(out, longitude >= -86.97 & longitude <= -86.78,
latitude >= 40.35 & latitude <= 40.49)
out
})
xy <- rbindlist(xy)
假设您使用 Windows PC 并且至少安装了 Microsoft Office 2007+,请考虑使用 JET/ACE SQL 引擎(.dll 文件)直接查询 CSV,这是非常适合 MS Access 的引擎。
下面包括两个使用 Access 或 Excel 的连接字符串。任何一个版本都可以工作,文件确实需要存在,但除了连接到 ACE 之外从未使用过。连接后,将从相同或不同路径查询 CSV 文件。
library(odbc)
# VERIFY AVAILABLE DSNs AND DRIVERS
odbcListDataSources()
# DSN VERSIONS
conn <- dbConnect(odbc::odbc(), DSN ="MS Access Database;DBQ=C:\Path\To\Access.accdb;");
conn <- dbConnect(odbc::odbc(), DSN ="Excel Files;DBQ=C:\Path\To\Excel.xlsx;");
# DRIVER VERSIONS
conn <- dbConnect(odbc::odbc(),
.connection_string = "Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=C:\Path\To\Access.accdb;");
conn <- dbConnect(odbc::odbc(),
.connection_string ="Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};DBQ=C:\Path\To\Excel.xlsx;");
# CSV QUERY
df <- dbGetQuery(conn, "SELECT t.*
FROM [text;database=C:\Path\To\CSV_Folder].Name_of_File.csv AS t
WHERE t.longitude BETWEEN -86.97 AND -86.78
AND t.latitude BETWEEN 40.35 AND 40.49;")
head(df)
dbDisconnect(conn)
循环中:
files = list.files(path = "G:/SafeGraph201708MidWest",
pattern = "*.csv",
recursive = TRUE,
full.names = TRUE)
df_list <- lapply(files, function(f)
df <- dbGetQuery(conn,
paste0("SELECT t.* ",
" FROM [text;database=G:\SafeGraph201708MidWest].", f, " AS t ",
" WHERE t.longitude BETWEEN -86.97 AND -86.78",
" AND t.latitude BETWEEN 40.35 AND 40.49;")
)
)
final_dt <- rbindlist(df_list)
您可以使用 data.table::fread()
中的能力来执行命令并 'read' 结果。
我假设您正在使用 windows,因此您可以在命令提示符中访问 findstr
功能。
因此,如果您可以在要提取的行上构建 'hits' 的正则表达式,则可以在将整个文件读入 R 之前过滤需要的行。这(可能)是一个 huuuge memory-saver 在较大的文件上,可能会大大加快您的工作流程。
示例数据
拉特说 coords.csv 看起来是这样的:
id,latitude,longitude
1,10,11
2,11,12
3,12,13
4,13,14
5,14,15
在此示例中,您要提取纬度在 12 和 14 之间以及经度在 11 和 13 之间的线
代码
#build a list of files (I created only one)
#make sure you use the full path (not relative)
x <- list.files( path = "C:/folder", pattern = "coord.csv", full.names = TRUE )
#build reges that only hits on rows with:
# latitude 12-14
# longitude 11-13
pattern = "^[0-9],1[2-4],1[1-3]$"
#read the file(s), extract the lines with match the regex-pattern
#and bind the resuklt to a data.table
rbindlist( lapply( x, function(x) {
fread( cmd = paste0( "findstr /R ", pattern, " ", x ), header = FALSE )
} ) )
输出
V1 V2 V3
1: 3 12 13