【问题标题】:Use RSQLite to manipulate data frame in r directly using SQL使用 RSQLite 在 r 中直接使用 SQL 操作数据框
【发布时间】:2021-06-27 17:29:27
【问题描述】:

我有一个表格的数据集

我想在 R 中使用 SQL 更改为下面的这种形式。

我知道我每天只需使用dplyr 就可以做到这一点,但这里的重点是学习使用 SQL 创建和操作小型关系数据库。

  • Price 需要转成数值。删除“R”和中间的空格。

  • coordinates需要变成2个坐标LongLat

  • floor size 需要从字符串中转换为数字,去掉空格和末尾的“m^2”。

最小工作示例

# Data to copy into sheet

       Price                            coordinates floor.size surburb       date
 R 1 750 000 -33.93082074573843, 18.857342125467635      68 m²     Jhb 2021-06-24
 R 1 250 000 -33.930077157927855, 18.85420954236195      56 m²     Jhb 2021-06-17
 R 2 520 000 -33.92954929205658, 18.857504799977896      62 m²     Jhb 2021-06-24

在 R markdown 中操作的代码

```{r}
#install.packages("RSQLite", repos = "http://cran.us.r-project.org")

library(readxl)
library(dplyr)
library(RSQLite)
library(DBI)
library(knitr)

db <- dbConnect(RSQLite::SQLite(), ":memory:")

knitr::opts_chunk$set(echo = TRUE)
knitr::opts_chunk$set(connection = "db")


# Import data
dataH <- read_excel("C:/Users/Dell/Desktop/exampledata.xlsx")

``` 

```{sql, connection = db}
# SQL code passed directly
```

编辑 1:

@Onyambu 的回答几乎有效。它正在产生坐标错误。例如,在下面的图像中,当coordinate 为“-33.930989501123, 18.857270308516927”时,最后两个坐标应该有一个以“18.85”而不是“.85”开头的Long。我该如何解决这个问题?

【问题讨论】:

  • 你看过sqldf吗?它允许对 data.frame(s) 进行 SQL 查询。
  • 请使用dput(x) 发布您的数据,因为我们不能在没有手动提取的情况下直接复制和粘贴。 (嵌入的空格使得read.table 和家人不能只解析它。)
  • 您还需要具体说明您使用的数据库引擎。 mysql、sqllite、postgresql等都有不同的功能需要实现。

标签: sql r r-markdown data-wrangling rsqlite


【解决方案1】:

使用基本的 sql 函数,您可以:

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE,connection = "db")
```

```{r}
db <- DBI::dbConnect(RSQLite::SQLite(), ":memory:")

txt <- "Price coordinates floor.size surburb date\n
     'R 1 750 000' '-33.93082074573843, 18.857342125467635' '68 m²' Jhb 2021-06-24\n
     'R 1 250 000' '-33.930077157927855, 18.85420954236195' '56 m²' Jhb 2021-06-17\n
     'R 2 520 000' '-33.92954929205658, 18.857504799977896' '62 m²' Jhb 2021-06-24"

dataH <- read.table(text = txt, header = TRUE) 
DBI::dbWriteTable(db, 'dataH', dataH)
```


```{sql}
SELECT REPLACE(SUBSTRING(price, 3, 100), ' ', '') price,
       replace(SUBSTRING(coordinates, 1, 20), ',', '') Lat,
       SUBSTRING(coordinates, 21, 255) Long,
       SUBSTRING(`floor.size`, 1, 2) floor_size,
       surburb,
       date
FROM dataH
```

【讨论】:

  • 对于最后一个块,使用:{sql, connection = db}
  • 嗨@Onyambu,坐标有问题。我将其作为编辑添加到问题中。
  • 也许@Parfait 知道如何解决坐标转换问题?
  • 可能是因为@Onyambu 的小数长度不同
  • @Parfait 我将connection = db 放在了设置块中,因此不需要再次包含它,但如果包含它也没问题
【解决方案2】:

您可以使用charindexsubstr 来做您需要的事情。我将使用sqldf 进行演示,它在后台使用 SQLite 的引擎。 (此查询与 Onyambu 的查询非常相似,但解决了一个文本选择问题。)

dat <- structure(list(Price = c("R 1 750 000", "R 1 250 000", "R 2 520 000"), coordinates = c("-33.93082074573843, 18.857342125467635", "-33.930077157927855, 18.85420954236195", "-33.92954929205658, 18.857504799977896"), floor.size = c("68 m²", "56 m²", "62 m²"), surburb = c("Jhb", "Jhb", "Jhb"), date = c("2021-06-24", "2021-06-17", "2021-06-24")), class = "data.frame", row.names = c(NA, -3L))

out <- sqldf::sqldf(
  "select cast(replace(substr(price,2,99),' ','') as real) as price,
          cast(substr(coordinates,1,charindex(',',coordinates)-1) as real) as lat,
          cast(substr(coordinates,charindex(',',coordinates)+1,99) as real) as long,
          cast(substr([floor.size],1,charindex('m',[floor.size])-1) as real) as [floor.size]
   from dat", method = "raw")

out
#     price       lat     long floor.size
# 1 1750000 -33.93082 18.85734         68
# 2 1250000 -33.93008 18.85421         56
# 3 2520000 -33.92955 18.85750         62

str(out)
# 'data.frame': 3 obs. of  4 variables:
#  $ price     : num  1750000 1250000 2520000
#  $ lat       : num  -33.9 -33.9 -33.9
#  $ long      : num  18.9 18.9 18.9
#  $ floor.size: num  68 56 62

out 输出中显示的位数是由于 R 的"digits" 选项,这些是numeric 类,如str 输出中所示。)

如果你改为sqldf(.., method="numeric"),你可以缩短它并删除所有cast(.. as ..)

out <- sqldf::sqldf(
  "select replace(substr(price,2,99),' ','') as price,
          substr(coordinates,1,charindex(',',coordinates)-1) as lat,
          substr(coordinates,charindex(',',coordinates)+1,99) as long,
          substr([floor.size],1,charindex('m',[floor.size])-1) as [floor.size]
   from dat", method = "numeric")

【讨论】:

    猜你喜欢
    • 2014-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多