我正在尝试编写一个循环来搜索data.frame B
(date_B[j]
)中的正确日期,并将相关值X_B[j]
复制到{{1与同一日期X_A[i]
相关的变量。
挑战在于:a)目标data.frame date_A[i]
有几个相同的日期,但b)没有系统地所有data.frame(B)的日期。 (B)包括所有需要的日期。因此,数据帧具有不同的长度。
问题:
数据框为:
A
我的目标是:
A =
date_A X_A
1 2010-01-01
2 2010-01-02
3 2010-01-03
4 2010-01-02
5 2010-02-03
6 2010-01-01
7 2010-01-02
.
.
.
20000
B=
date_B X_B
1 2010-01-01 7.9
2 2010-01-02 8.5
3 2010-01-03 2.1
.
.
400
我编写了以下循环,但由于某种原因,它没有找到超越第一行的方式。换句话说,它不会更改其他 A=
date_A X_A
1 2010-01-01 7.9
2 2010-01-02 8.5
3 2010-01-03 2.1
4 2010-01-02 8.5
5 2010-02-03 2.1
6 2010-01-01 7.9
7 2010-01-02 8.5
单元格的值,尽管循环会无休止地运行。
X_A
感谢您的帮助。
答案 0 :(得分:7)
有了这种问题,merge
会让事情变得更容易。以你的例子我没有与第七行匹配,但也许你有一个错字。我的A数据框只有date_A列。如果您想重命名X_B列,那么names()<-
将轻松完成;
merge(A, B, by.x=1, by.y=1, all.x=TRUE)
#---result---
date_A X_B
1 2010-01-01 7.9
2 2010-01-01 7.9
3 2010-01-02 8.5
4 2010-01-02 8.5
5 2010-01-02 8.5
6 2010-01-03 2.1
7 2010-02-03 NA
答案 1 :(得分:2)
有了这些数据:
A <- data.frame( date_A = c('2010-01-01', '2010-01-02', '2010-01-03', '2010-01-02',
'2010-02-03', '2010-01-01', '2010-01-02') )
B <- data.frame(
date_B = c('2010-01-01','2010-01-02','2010-01-03'),
X_B = c(7.9,8.5,2.1))
您可以使用match()
按正确的顺序索引X_B
值:
A$X_A <- B$X_B[match(A$date_A,B$date_B)]
match()
返回B$date_B
中A$date_A
位置的索引。另一个使用的技巧是使用因子的级别作为索引:
A$X_A <- B$X_B[A$date_A]
这是有效的,因为每个因子都按排序顺序排列,并对应于数值(1,2,3 ...)。因此,如果B
根据这些级别排序,则返回正确的索引。 (您可能希望对B
进行排序以确保:B <- B[order(B$date_B),]
)
至于为什么循环不起作用。首先,我认为你真的不想在R脚本中使用;
。它使代码更难阅读。最好的是如果你学会编写清晰的代码。在您的代码中,您可以使用更一致的分配器并使用正确的缩进。例如:
i <- 1
j <- 1
while (i <= nrow(A))
{
while (j <= nrow(B))
{
if (A$date_A[i]==B$date_B[j]) A$X_A[i] <- B$X_B[j]
j <- j+1
if (j == nrow(B)) i <- i+1
j <- 1
}
}
这是你的代码,但阅读起来要清楚得多。对我来说,这不会运行,因为级别不可比(由于拼写错误)所以我进行了as.character()
调用。在真实数据集中可能不需要这样做。
索引会立即显示最大问题:您在j <- 1
部分之外放错了if (j == nrow(B))
。使用;
终止该行,从而终止条件部分。因为这个j
在每个循环中都设置为1。
更改它会使其运行得更好,但是仍然会出现错误,因为while
的{{1}}循环可能在j
大于{{1}中的行数之前完成}}。这可以通过设置i
语句并将A
个循环折叠为一个来更改。最后,您需要将AND
语句设置为大于while
中的行数,或者省略一行。这应该有效:
if
但这只是为了表明出了什么问题,我从来没有建议这样做过这样的事情。即使你真的想要使用循环,你也可能更适合使用B
循环。
答案 2 :(得分:2)
哇!你的代码让我害怕。至少,为这种事情使用for循环(虽然@Dwin的解决方案是解决这个问题的方法):
for(i in seq(nrow(A)))
{
for(j in seq(nrow(B)))
{
if(A$date_A[i]==B$date_B[j])
{
A$X_A[i] <- B$X_B[j]
}
}
}
这样可以防止在while循环结束时手动尝试增加的所有丑陋(在你自己的代码中,顺便说一下,j = 1需要移到内括号之外)。
注意:此代码与您的代码一样,当B包含两行与A中的日期相同时,它不会解决问题(它将始终使用B中该行日期的最后一行的值)。它可以帮助您理解而不是简单的增量循环。