【问题标题】:Populate new column row-by-row using values from different existing columns, using date as selection criteria使用来自不同现有列的值,使用日期作为选择标准,逐行填充新列
【发布时间】:2018-10-30 14:38:25
【问题描述】:

我正在使用 R 编辑 GPS 点的 csv。该表看起来像这样:

ID    DATE        2002.08.01    2002.08.02    2002.08.03    2002.08.04
1     8/1/2002    56            41            54            89
2     8/2/2002    65            59            69            10
3     8/2/2002    66            51            61            5
4     8/3/2002    11            21            12            32

上表中以日期作为列标题的每一列都是该 GPS 点某一特定日期的雪深。我想要的是一个新列 SNOW_DEPTH只有 具有该 GPS 点的正确日期的雪深。在我给出的示例数据中,我正在寻找的解决方案是这样的:

ID    DATE        SNOW_DEPTH
1     8/1/2002    56
2     8/2/2002    59
3     8/2/2002    51
4     8/3/2002    12

请注意,解表中SNOW_DEPTH 的值是根据该行的雪深值填充的,但用于填充的列取决于日期。

我确实想按名称列出每一列,因为在我的真实数据中有数千列(所有列都以日期作为列标题)。是否有一个简单的、基于脚本的 R 解决方案来解决我的困境?

【问题讨论】:

    标签: r csv dataframe


    【解决方案1】:

    这是使用tidyverse 软件包套件的解决方案。请注意,我假设 DATE 存储为字符或因子。

    df <- read_table("ID    DATE        2002.08.01    2002.08.02    2002.08.03    2002.08.04
    1     8/1/2002    56            41            54            89
    2     8/2/2002    65            59            69            10
    3     8/2/2002    66            51            61            5
    4     8/3/2002    11            21            12            32")
    
    library(tidyverse)
    df %>%
      gather(COL_DATE, SNOW_DEPTH, -ID, -DATE) %>%
      mutate( # this converts both `DATE` and `COL_DATE` to the date-time format.  If `DATE` is already in this format, skip the first conversion (you still need to convert `COL_DATE`).
        DATE = as.Date(DATE,format = "%m/%d/%Y"),
        COL_DATE = as.Date(COL_DATE, format = "%Y.%m.%d")
      ) %>%
      filter(DATE == COL_DATE) %>%
      select(-COL_DATE)
    

    【讨论】:

    • 这似乎是我的问题的解决方案,它在测试数据集上运行良好。但是,当我在我的实际数据上运行它时,会出现以下错误:Error in base::assign(nm, data[[nm]], envir = env_) : variable names are limited to 10000 bytes 有什么想法吗?
    • 你知道哪个命令给你错误吗? (分段运行,例如从df %&gt;% gather(COL_DATE, SNOW_DEPTH, -ID, -DATE) 开始查找)
    • 第一部分:df %&gt;% gather(COL_DATE, SNOW_DEPTH, -ID, -DATE)
    • 我不确定问题出在哪里。显然,我们定义的两个变量(COL_DATESNOW_DEPTH)不会引起问题。从技术上讲,日期列在技术上不是有效的列名,但我们正在将它们从列名移动到变量。我可能会尝试系统地在日期列的不同子集上运行代码,直到我找出导致问题的原因。那时,如果您无法弄清楚错误发生的原因,希望您有足够的数据来创建可重现的示例,以便这里的人可以。
    • 为避免出现问题,我使用read.csv(check.names=FALSE) 而不是read_tableread.table。现在可以正常使用了。
    【解决方案2】:

    我认为你最好的办法是制作一个“长”文件,其中ID/date/value 在页面下方运行,然后将其合并回IDdate 上的初始数据匹配:

    merge(
      transform(dat[1:2], ind=format(as.Date(DATE, format="%m/%d/%Y"), "%Y.%m.%d")),
      cbind(dat["ID"], stack(dat[-(1:2)]))
    )
    
    #  ID        ind     DATE values
    #1  1 2002.08.01 8/1/2002     56
    #2  2 2002.08.02 8/2/2002     59
    #3  3 2002.08.02 8/2/2002     51
    #4  4 2002.08.03 8/3/2002     12
    

    cbind(dat["ID"], stack(dat[-(1:2)])) 给出长文件:

    #   ID values        ind
    #1   1     56 2002.08.01
    #2   2     65 2002.08.01
    #3   3     66 2002.08.01
    # <snip>
    

    并且transform(dat[1:2], ind=format(as.Date(DATE, format="%m/%d/%Y"), "%Y.%m.%d")) 将正确格式的日期返回给merge

    #  ID     DATE        ind
    #1  1 8/1/2002 2002.08.01
    #2  2 8/2/2002 2002.08.02
    #3  3 8/2/2002 2002.08.02
    #4  4 8/3/2002 2002.08.03
    

    在此示例中,dat 是:

    dat <- read.table(text="ID    DATE        2002.08.01    2002.08.02    2002.08.03    2002.08.04
    1     8/1/2002    56            41            54            89
    2     8/2/2002    65            59            69            10
    3     8/2/2002    66            51            61            5
    4     8/3/2002    11            21            12            32", header=TRUE, stringsAsFactors=FALSE)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-05
      • 2012-09-30
      • 1970-01-01
      • 2017-09-18
      • 2013-01-26
      • 2015-02-25
      相关资源
      最近更新 更多