【问题标题】:How to add key-value pair like dictionary?如何像字典一样添加键值对?
【发布时间】:2017-09-03 09:47:02
【问题描述】:

我的数据(总共 8532 obs)如下所示:

Prd_Id  Weight
DRA24   19.35
DRA24   NA
DRA24   NA
DRA24   19.35
DRA24   19.35
DRA59   8.27
DRA59   8.27
DRA59   8.27
DRA59   8.27
DRA59   NA
DRA59   NA

基本上问题是有很多对Prd_idweight,其中一些Prd_id没有提到weight,例如我在数据中显示的第一个只有第二个和第三个不是,所以我知道weight 的值,我只需要用它替换 NA,所有相同的Prd_id 将具有相同的weight 但在 R 中没有像字典这样的东西,所以我觉得很难来解决这个问题。我尝试使用for loop,但这需要很长时间,我的代码如下所示:

for(i in 1:nrow(bms)){
  for(j in 1:1555){
    if(spl$Prd_Id[j]==bms$Prd_Id[i]){
      bms$weight[i]=spl$weight[j]
    }
  }
}

bms 是整个 data (8532 obs),spl (1555 obs) 是 bms 的子集,唯一值为 Prd_Id

【问题讨论】:

  • 目前尚不清楚为什么字典是缺失值的首选解决方案。您可以简单地删除 (complete.cases) 或估算它们(有几个软件包提供)。如果您需要从 data.frame 进行查找(如您在此处所示),您可以使用“连接”运算符之一(无论是基本 R 中的 mergedplyr::*_join 函数之一,还是等效的在data.table)。如果spl 只是bms 的一个样本,但它有缺失值(存在于bms 中),那么你的问题不是字典,你的问题是你的抽样技术。跨度>
  • 实际上有很多对 Prd_id 和重量,其中一些 Prd_id 没有提到重量,例如我在数据中显示的第一个有但第二个和第三个没有所以我知道权重的值,我只需要用它替换 NA,所有相同的 Prd_id 将具有相同的权重,这就是为什么我正在考虑创建一个字典,它将键作为 Prd_id,值作为权重。其次,spl 没有缺失值,它具有 Prd_id 的所有唯一值和相应的权重

标签: r list for-loop missing-data


【解决方案1】:

正如@r2evans 建议的那样,您可以使用类似 SQL 的连接策略,结合 dplyr 的 coalescethis 看起来像这样:

library(dplyr)

# create 'bms'.
bms <- data_frame(
  Prd_Id = c("DRA24", "DRA24", "DRA24", "DRA24", "DRA24", "DRA59", "DRA59", "DRA59", "DRA59", "DRA59", "DRA59"),
  Weight = c(19.35, NA, NA, 19.35, 19.35, 8.27, 8.27, 8.27, 8.27, NA, NA)
)

# create 'spl'
spl <- bms %>% filter(!is.na(Weight)) %>% filter(!duplicated(Prd_Id))

# SQL-like join and coalesce strategy
res <- bms %>% 
  left_join(spl, by = "Prd_Id", suffix = c("_bms", "_spl")) %>% 
  mutate(Weight = coalesce(Weight_bms, Weight_spl)) %>%
  select(-Weight_bms, -Weight_spl)

【讨论】:

  • 谢谢,left_join 是我要找的 :)
【解决方案2】:

不需要left_join

bms %>% 
  group_by(Prd_Id) %>% 
  mutate(Weight = Weight[!is.na(Weight)][1])

first 的另一种方式:

bms %>% 
  group_by(Prd_Id) %>% 
  mutate(Weight = first(Weight[!is.na(Weight)]))

结果:

# A tibble: 11 x 2
# Groups:   Prd_Id [2]
   Prd_Id Weight
    <chr>  <dbl>
 1  DRA24  19.35
 2  DRA24  19.35
 3  DRA24  19.35
 4  DRA24  19.35
 5  DRA24  19.35
 6  DRA59   8.27
 7  DRA59   8.27
 8  DRA59   8.27
 9  DRA59   8.27
10  DRA59   8.27
11  DRA59   8.27

当然,你也可以在原版 R 中做到这一点:

transform(bms, Weight = ave(Weight, Prd_Id, FUN = function(x) x[!is.na(x)][1]))

结果是一样的:

   Prd_Id Weight
1   DRA24  19.35
2   DRA24  19.35
3   DRA24  19.35
4   DRA24  19.35
5   DRA24  19.35
6   DRA59   8.27
7   DRA59   8.27
8   DRA59   8.27
9   DRA59   8.27
10  DRA59   8.27
11  DRA59   8.27

【讨论】:

  • 感谢您的帮助
【解决方案3】:

这是一个基本的 R 解决方案

# example data
bms <- data.frame(
  Prd_Id = c("DRA24", "DRA24", "DRA24", "DRA24", "DRA24", "DRA59", "DRA59", "DRA59", "DRA59", "DRA59", "DRA59"),
  Weight = c(19.35, NA, NA, 19.35, 19.35, 8.27, 8.27, 8.27, 8.27, NA, NA)
)

# create key-value pairs
spl <- unique(bms[!is.na(bms[,"Weight"]),])
spl <- setNames(spl[,"Weight"], spl[,"Prd_Id"])

# fill NAs
idx <- which(is.na(bms[,"Weight"]))
bms[idx,"Weight"] <- spl[bms[idx, "Prd_Id"]]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-16
    • 2011-11-04
    • 2016-10-29
    • 2022-07-25
    • 2021-03-14
    • 2019-11-07
    • 2018-05-27
    • 1970-01-01
    相关资源
    最近更新 更多