如何用R中的字符替换数值?

时间:2014-09-09 21:02:42

标签: r

我有这样的文件。

"1" 10 2 0 0 0 0 0 0 0 0 0 0 0 4 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0
"2" 10 3 6 17 11 15 8 17 14 1 42 21 22 15 9 9 17 12 9 16 4 8 12 29 23 11 0 0 0 0
"3" 10 4 39 39 14 33 16 23 37 21 29 22 46 26 16 26 21 22 21 10 16 3 10 14 20 12 6 0 0 0
"4" 100 18 0 0 0 1 0 0 0 0 0 0 2 0 0 1 0 2 8 5 2 1 2 4 9 6 4 3 0 0
.....................

我想要做的是,用字符替换第4列以后的值,即如果值在0到10之间,那么它将被字符'a'替换,如果它在10到20之间,它将由字符b替换,依此类推。

例如,输出文件的格式为

"1" 10 2 0 0 0 0 0 0 0 0 0 0 0 a 0 0 a 0 0 0 0 0 a 0 0 0 0 0 0 0
.............................

我怎样才能在R中做到?有没有我可以自动分配字符,因为目前我使用两个for循环并按范围对值进行编码。

编辑:我的方法:

> for ( i in 1:nrow(x) )
+     for ( j in j:ncol(x) )
+         {
+             if (x[i,j] < 10 && x[i,j] > 0 )
+                 x[i,j] = a
+             else if ( x[i,j] < 20 && x[i,j] > 10 )
+                 x[i,j] = b
+         }

以上是我的方法。这显示条件错误,我知道会花费很多时间,因为它涉及使用两个for循环。

3 个答案:

答案 0 :(得分:1)

一种可能的解决方案是创建一个与之匹配的虚拟数据集,然后将所有非零值与之匹配(假设df是您的数据集)

matchData <- data.frame(lets = c(0, rep(letters, each = 10)),
                        nums = c(0, seq_len(length(letters)*10)))

df[, -seq_len(3)] <- sapply(df[, -seq_len(3)], function(x) matchData$lets[match(x, matchData$nums)])
df
#   V1  V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17 V18 V19 V20 V21 V22 V23 V24 V25
# 1  1  10  2  0  0  0  0  0  0   0   0   0   0   0   a   0   0   a   0   0   0   0   0   a   0
# 2  2  10  3  a  b  b  b  a  b   b   a   e   c   c   b   a   a   b   b   a   b   a   a   b   c
# 3  3  10  4  d  d  b  d  b  c   d   c   c   c   e   c   b   c   c   c   c   a   b   a   a   b
# 4  4 100 18  0  0  0  a  0  0   0   0   0   0   a   0   0   a   0   a   a   a   a   a   a   a
#   V26 V27 V28 V29 V30 V31
# 1   0   0   0   0   0   0
# 2   c   b   0   0   0   0
# 3   b   b   a   0   0   0
# 4   a   a   a   a   0   0

答案 1 :(得分:0)

您可以使用ascii代码和基于您的值/ 10(没有余数)的偏移量...

mydat = c(10,2,0,19,20,19,0,0)

# Convert a number divided by 10 to its offset (hat tip to MrFlick for `letters`
# this uses the cryptic looking %/% operator for division without remainder

char10 = letters[1+(md %/% 10)] 

# convert zeroes, and if desired replace column 1:4 with original data 
char10[md==0] = 0 

输出:

> char10
[1] "b" "a" "0" "b" "c" "b" "0" "0"

答案 2 :(得分:0)

我认为以下内容将会很接近,只是一个快速回答,希望对您有所帮助。您必须通过此方法应用于整个数据框。还有我在这里没有处理过的强制,所以在单行测试时,所有内容都被强制转换为char。

基本思想是,如果你想要1-10对应&#34; a&#34;,11-20对应&#34; b&#34;,那么我们可以通过除以数字得到它到10,然后调用上限。 1-10然后映射到1,11-20然后映射到2,依此类推。字母[1]映射到&#34; a&#34;,字母[2]映射到&#34; b&#34;等等,这样我们就可以获得所需的功能。

 #everything coerced to char, I know
 testVect<-c("2", 10, 3, 6, 17, 11, 15, 8 ,17, 14, 1, 42, 21, 22, 15, 9, 9, 17, 12, 9, 16, 4, 8, 12 ,29, 23, 11, 0, 0 ,0 ,0)

 testAfter4<-sapply(testVect[4:length(testVect)], 
        function(entry) {
              ifelse(entry==0, 0, letters[ceiling(as.numeric(entry)/10)])
         } )
 #need to cast entry back to numeric as it was coerced to char when initializing testVect

 testVect[4:length(testVect)]<-testAfter4

 testVect
 #[1] "2"  "10" "3"  "a"  "b"  "b"  "b"  "a"  "b"  "b"  "a"  "e"  "c"  "c"  "b" 
 #[16] "a"  "a"  "b"  "b"  "a"  "b"  "a"  "a"  "b"  "c"  "c"  "b"  "0"  "0"  "0" 
 #[31] "0"