【问题标题】:R - compare rows consecutively in two data frames and return a valueR - 连续比较两个数据帧中的行并返回一个值
【发布时间】:2014-01-30 02:57:21
【问题描述】:

我有以下两个数据框:

df1 <- data.frame(month=c("1","1","1","1","2","2","2","3","3","3","3","3"),
             temp=c("10","15","16","25","13","17","20","5","16","25","30","37"))


df2 <-  data.frame(period=c("1","1","1","1","1","1","1","1","2","2","2","2","2","2","3","3","3","3","3","3","3","3","3","3","3","3"),
              max_temp=c("9","13","16","18","30","37","38","39","10","15","16","25","30","32","8","10","12","14","16","18","19","25","28","30","35","40"),
              group=c("1","1","1","2","2","2","3","3","3","3","4","4","5","5","5","5","5","6","6","6","7","7","7","7","8","8"))

我想:

  1. 逐行检查df1month列中的值是否与df2period列中的值匹配,df1$month == df2$period

  2. 如果第 1 步不是 TRUE,df1$month != df2$period,然后重复第 1 步并将df1 中的值与df2 的下一行中的值进行比较,并且以此类推,直到df1$month == df2$period

  3. 如果是df1$month == df2$period,检查df1temp列的值是否小于或等于df2max_temp列的值, df1$temp &lt;= df$max_temp.

  4. 如果是df1$temp &lt;= df$max_temp,则在该行中为df2 中的group 列返回值,并将此值添加到df1,在一个名为"new_group" 的新列中。

    李>
  5. 如果第 3 步不正确,df1$temp &gt; df$max_temp,则返回第 1 步,将df1 中的同一行与df2 中的下一行进行比较。

我想要的输出数据框的一个例子是:

df3 <- data.frame(month=c("1","1","1","1","2","2","2","3","3","3","3","3"),
             temp=c("10","15","16","25","13","17","20","5","16","25","30","37"),
             new_group=c("1","1","1","2","3","4","4","5","6","7","7","8"))

我一直在玩ifelse 函数,需要一些帮助或重新定向。谢谢!

【问题讨论】:

  • 您是否有意将您的数据保存为字符串?
  • 数据文件实际上是制表符分隔的文本文件,我使用 read.table 作为数据帧上传到 R 中。作为一个 R 新手,我不知道数据是字符串。
  • 数字周围的引号告诉你你有字符串。另外,请注意伪装成因子的字符串,您将拥有read.table(.... stringsAsFactors=TRUE)(令人讨厌的是默认值)
  • 我给出的 data.frame 代码只是试图重现我在 R. Cheers 中使用的数据帧。
  • 感谢您的洞察!

标签: r if-statement compare dataframe


【解决方案1】:

我发现计算new_group 的过程很难按照说明进行。据我了解,您正在尝试在df1 中创建一个名为new_group 的变量。对于df1 的行inew_group 的值是df2 中第一行的group 值:

  1. 索引为i 或更高
  2. 有一个period 值匹配df1$month[i]
  3. 具有不小于df1$temp[i]max_temp

我通过在df1 的行索引上调用sapply 来解决这个问题:

fxn = function(idx) {
  # Potentially matching indices in df2
  pm = idx:nrow(df2)

  # Matching indices in df2
  m = pm[df2$period[pm] == df1$month[idx] &
         as.numeric(as.character(df1$temp[idx])) <=
         as.numeric(as.character(df2$max_temp[pm]))]

  # Return the group associated with the first matching index
  return(df2$group[m[1]])
}
df1$new_group = sapply(seq(nrow(df1)), fxn)
df1
#    month temp new_group
# 1      1   10         1
# 2      1   15         1
# 3      1   16         1
# 4      1   25         2
# 5      2   13         3
# 6      2   17         4
# 7      2   20         4
# 8      3    5         5
# 9      3   16         6
# 10     3   25         7
# 11     3   30         7
# 12     3   37         8

【讨论】:

  • 感谢您提供有用的代码。不计算 new_group 的值,而只是将 df2$group 的值放入 df1$new_group 列。希望这能让它更清楚。干杯。
  • 是的,我发布的代码就是这样做的。看起来您对 SO 还很陌生,并且没有接受您在以前的问题中收到的好的答案。如果我的解决方案或@RicardoSaporta 的解决方案解决了您的问题,请记得选中绿色复选框来接受它。
【解决方案2】:
library(data.table)
dt1 <- data.table(df1, key="month")
dt2 <- data.table(df2, key="period")

## add a row index
dt1[, rn1 := seq(nrow(dt1))]

dt3 <- 
unique(dt1[dt2, allow.cartesian=TRUE][, new_group := group[min(which(temp <= max_temp))], by="rn1"], by="rn1")

## Keep only the columns you want
dt3[, c("month", "temp", "max_temp", "new_group"), with=FALSE]

    month temp max_temp new_group
 1:     1    1       19         1
 2:     1    3       19         1
 3:     1    4       19         1
 4:     1    7       19         1
 5:     2    2        1         3
 6:     2    5        1         3
 7:     2    6        1         4
 8:     3   10       18         5
 9:     3    4       18         5
10:     3    7       18         5
11:     3    8       18         5
12:     3    9       18         5

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-30
    • 2021-09-16
    • 2017-04-26
    • 1970-01-01
    • 1970-01-01
    • 2015-07-19
    相关资源
    最近更新 更多