【问题标题】:assigning values to specific cells based on the values in a specific column根据特定列中的值将值分配给特定单元格
【发布时间】:2019-10-04 01:32:48
【问题描述】:

以下是有助于为以下问题创建样本的数据:

df1 <- data.frame(ID = c(1:5), Order_status_1 = c(1,1,0,0,1), Order_time_1 = c(20, 30, 0, 0, 47), 
Order_status_1 = c(0,1,1,1,1), Order_time_1 = c(0, 36, 12, 24, 88), Order_status_3 = c(0, 1, 1, 0, 
0), Order_time_3 = c(0, 40, 25, 0, 0), Order_status_4 = c(0, 1, 0, 0, 0), Order_time_3 = c(0, 65, 0, 
0, 0),  Order_close_date = c(100, 200, 300, 400, 500)  )

预期输出

df2 <- data.frame(ID = c(1:5), Order_status_1 = c(1,1,0,0,1), Order_time_1 = c(20, 30, 0, 0, 47), 
Order_status_2 = c(0,1,1,1,1), Order_time_2 = c(100, 36, 12, 24, 88), Order_status_3 = c(0, 1, 1, 0, 
0), Order_time_3 = c(100, 40, 25, 400, 500), Order_status_4 = c(0, 1, 0, 0, 0), Order_time_4 = 
c(100, 65, 300, 400, 500),  Order_close_date = c(100, 200, 300, 400, 500)  ) 

如您所见,最后一个(时间)列中的值被复制到包含 0 -> 的时间列中,位于非零时间值列之后。

我强烈认为循环应该从最后一个时间列开始检查 (0),直到它达到非零值,然后在相应的单元格中插入值 (100,200,300,400,500)。数据包含多行,这只是其中的一个示例。因此,请提供可以运行代码超过 1000 行的解决方案(例如 for 或 if 循环)。

【问题讨论】:

标签: r


【解决方案1】:

在基数 R 中,我们可以在 "time" 列上按行使用 apply,并将第一次出现非零值后的 0 替换为最后一列值。

time_columns <- c(grep("time", names(df1)), ncol(df1))

df1[time_columns] <- t(apply(df1[time_columns], 1, function(x) 
            replace(x, x == 0 & seq_along(x) > which.max(x !=0), x[length(x)])))

【讨论】:

  • 它给出了以下错误:[&lt;-.data.table(*tmp*, time_column, value = c(2, 4, 6, 8, 中的错误:提供 325 项分配给列的 13 项'ID'。RHS 长度必须为 1(单个值即可)或与 LHS 长度完全匹配。如果您希望“回收”RHS,请明确使用 rep() 以使代码读者清楚这一意图。另外:警告信息:在[&lt;-.data.table(*tmp*, time_column, value = c(2, 4, 6, 8, := 的25列矩阵RHS将被视为一个向量
  • @AashayMehta 看起来你有一个 data.table 而在示例中你有数据框。您可以将数据转换为数据框然后尝试吗? df1 &lt;- data.frame(df1)
  • 知道了!非常感谢@Ronak Shah
【解决方案2】:

使用data.table 转换为长格式的选项,更新适当的行,然后根据所需的输出转换为宽格式:

library(data.table)

#convert into long format
DT <- melt(setDT(df1), id.vars=c("ID", "Order_close_date"), 
    measure.vars=patterns("^Order_status", "^Order_time"),
    value.name=c("Order_status", "Order_time"),
    variable.name="Order", variable.factor=FALSE)

#update rows where Order_status is 0 and there is a 1 before then
DT[DT[, .I[Order_status==0 & cumsum(Order_status) > 0], ID]$V1, 
    Order_time := Order_close_date]

#pivot into wide format
ans <- dcast(DT, ID + Order_close_date ~ Order, value.var=c("Order_status","Order_time"))
setcolorder(ans, names(df1))[]

输出:

  ID Order_status_1 Order_time_1 Order_status_2 Order_time_2 Order_status_3 Order_time_3 Order_status_4 Order_time_4 Order_close_date
1  1              1           20              0          100              0          100              0          100              100
2  2              1           30              1           36              1           40              1           65              200
3  3              0            0              1           12              1           25              0          300              300
4  4              0            0              1           24              0          400              0          400              400
5  5              1           47              1           88              0          500              0          500              500

【讨论】:

    猜你喜欢
    • 2022-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多