我有一个data.frame df
> df
V1 V2
1 a b
2 a e
3 a f
4 b c
5 b e
6 b f
7 c d
8 c g
9 c h
10 d g
11 d h
12 e f
13 f g
14 g h
我发现每个元素出现的频率考虑到 V1 列,并按升序对 Freq 列进行排序
>dfFreq <- as.data.frame(table(df$V1))
Var1 Freq
1 a 3
2 b 3
3 c 3
4 d 2
5 e 1
6 f 1
7 g 1
>dfFreqSorted <- dfFreq[order(dfFreq$Freq),]
Var1 Freq
5 e 1
6 f 1
7 g 1
4 d 2
1 a 3
2 b 3
3 c 3
现在我要做的是根据原始data.frame创建一个新的data.frame,使每个&#34; Var1 &#34;项目在&#34; dfFreqSorted &#34;根据它的频率使用,但每次从&#34; dfFreqSorted &#34;的顶部开始使用在下面给出结果如下:
所以考虑第一个Var1项目是&#34; e &#34;所以第一个匹配的行是&#34; e &#34;在 df 的 V1 列中(e,f),这将是新data.frame中的第一项。 我想这可以使用:
完成>subset(df, V1==dfFreqSorted$Var[1])[1,]
V1 V2
12 e f
因此,如果我使用for循环并循环遍历 dfFreqSorted 的 Var1 列中的所有元素,并使用上面的子集命令并将返回的结果rbind到另一个数据.frame我会有类似下面的内容
V1 V2
12 e f
13 f g
14 g h
10 d g
1 a b
4 b c
7 c d
现在,此结果会显示每个 Var1 项目一次。我需要如下所示的剩余行,以便在完成 Var1 的所有行的第一次迭代后,循环应该再次开始并检查所有 Var1 现在其频率超过1,并找到该元素的 df 的下一行,以便在同一data.frame中生成的剩余行如下所示:
11 d h
2 a e
5 b e
8 c g
3 a f
6 b f
9 c h
正如您在上面所看到的,所有元素都在 Var1 中被考虑,其频率为1,首先使用频率大于1的那些元素(即2)并在下一次迭代中使用一次使用频率大于2(即3)的那些。使用,以便从df中获取该元素的相应未使用行。
因此,简而言之,df的所有元素都排列在一个新的data.frame中,这样元素按其频率的升序使用,但是在每次迭代中使用一次,然后根据它们的频率使用两次或三次。
我并不是要求整个代码只是为了实现目标的指导。提前谢谢。
答案 0 :(得分:1)
Hello @akrun我是初学者,所以解决方案可能真的是一个初学者级别的方法,但它完全解决了我的问题。
> a<-read.table("isnodes.txt")
> a
V1 V2
1 a b
2 a e
3 a f
4 b c
5 b e
6 b f
7 c d
8 c g
9 c h
10 d g
11 d h
12 e f
13 f g
14 g h
> aF<-as.data.frame(table(a$V1))
> aF
Var1 Freq
1 a 3
2 b 3
3 c 3
4 d 2
5 e 1
6 f 1
7 g 1
> aFsorted <- aF[order(aF$Freq),]
> aFsorted
Var1 Freq
5 e 1
6 f 1
7 g 1
4 d 2
1 a 3
2 b 3
3 c 3
> sortedEdgeList <- a[-c(1:nrow(a)),]
> sortedEdgeList
[1] V1 V2
<0 rows> (or 0-length row.names)
> aFsorted <- cbind(aFsorted, Used=0)
> aFsorted
Var1 Freq Used
5 e 1 0
6 f 1 0
7 g 1 0
4 d 2 0
1 a 3 0
2 b 3 0
3 c 3 0
> maxFreq <- max(aFsorted$Freq)
> maxFreq
[1] 3
> for(i in 1:maxFreq){
+ rows<-nrow(aFsorted)
+ for(j in 1:rows){
+ Var1Value<-aFsorted$Var[j]
+ Var1Edge<-a[match(aFsorted$Var1[j],a$V1),]
+ sortedEdgeList<-rbind(sortedEdgeList,Var1Edge)
+ a<-a[!(a$V1==Var1Edge$V1 & a$V2==Var1Edge$V2),]
+ aFsorted$Used[j]=aFsorted$Used[j]+1
+ }
+ if(aFsorted$Used==aFsorted$Freq){
+ aFsorted<-aFsorted[!(aFsorted$Used==aFsorted$Freq),]
+ }
+ }
Warning messages:
1: In if (aFsorted$Used == aFsorted$Freq) { :
the condition has length > 1 and only the first element will be used
2: In if (aFsorted$Used == aFsorted$Freq) { :
the condition has length > 1 and only the first element will be used
3: In if (aFsorted$Used == aFsorted$Freq) { :
the condition has length > 1 and only the first element will be used
> sortedEdgeList
V1 V2
12 e f
13 f g
14 g h
10 d g
5 a b
4 b c
7 c d
11 d h
2 a e
51 b e
8 c g
3 a f
6 b f
9 c h
答案 1 :(得分:0)
我不确定这是你想要的,但它可能很接近。它在概念上有助于将频率保持在原始数据框中。
library("plyr")
set.seed(3)
df <- data.frame(V1 = sample(letters[1:10], 20, replace = TRUE),
V2 = sample(letters[1:10], 20, replace = TRUE),
stringsAsFactors = FALSE)
df$freqV1 <- NA_integer_
for (i in 1:nrow(df)) {
df$freqV1[i] <- length(grep(pattern = df$V1[i], x = df$V1))
}
df2 <- arrange(df, freqV1, V2) # you may want just arrange(df, freqV1)
给出:
V1 V2 freqV1
1 h c 1
2 d a 2
3 d b 2
4 c c 2
5 c j 2
6 b c 3
7 g c 3
8 b f 3
9 g h 3
10 g h 3
11 b i 3
12 i a 4
13 i c 4
14 i d 4
15 i f 4
16 f b 5
17 f d 5
18 f d 5
19 f e 5
20 f f 5