在R

时间:2018-06-18 16:48:19

标签: r excel vba replace excel-2010

我试图覆盖excel中的逻辑,但是因为我不是excel的专业人员而失败。

以下是我的数据:

  C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 C11 C12 C13 C14 C15
1 12  3  3  4  5  6  7  7  7   7   7   7   7   7   7
2  1  4  5  5  5  5  5  5  6   7   8   8   8   8   8
3  3  4  4  4  4 45 32 57 23  23  23  23  23  23  23

如您所见,在第一行中,从最后一列开始,有多个7&#39。相似,对于从最后一列开始的第二行 有多个8&s;对于row3,有多个23&.s。

我想将7&8,8&23和23的多个列替换为#N / A,并且只保留结果中的前7个。 我用一个简单的逻辑尝试了它,其中IF(C15<> C14,C15," N / A"),然而这个逻辑失败了,因为它也转换了行级别的先前重复值

以下是我寻找最终结果的方法。

  C1 C2 C3 C4 C5 C6 C7   C8   C9  C10  C11  C12  C13  C14  C15
1 12  3  3  4  5  6  7 #N/A #N/A #N/A #N/A #N/A #N/A #N/A #N/A
2  1  4  5  5  5  5  5    5    6    7    8 #N/A #N/A #N/A #N/A
3  3  4  4  4  4 45 32   57   23 #N/A #N/A #N/A #N/A #N/A #N/A

我可以在Excel中执行此操作,还是需要在R中找到一些代码?

任何线索都会受到赞赏。

谢谢, 杰

数据:

df <- structure(list(C1 = c(12, 1, 3), C2 = c(3, 4, 4), C3 = c(3, 5, 4), 
               C4 = c(4, 5, 4), C5 = c(5, 5, 4), C6 = c(6, 5, 45), 
               C7 = c(7, 5, 32), C8 = c(7, 5, 57), C9 = c(7, 6, 23), 
               C10 = c(7, 7, 23), C11 = c(7, 8, 23), C12 = c(7, 8, 23), 
               C13 = c(7, 8, 23), C14 = c(7, 8, 23), C15 = c(7, 8, 23)), 
          .Names = c("C1", "C2", "C3", "C4", "C5", 
                     "C6", "C7", "C8", "C9", "C10",
                     "C11", "C12", "C13", "C14", "C15"), 
          row.names = c(NA, -3L), class = "data.frame")

6 个答案:

答案 0 :(得分:2)

以下是使用rleid中的data.table的R解决方案:

library(data.table)
df[t(apply(df, 1, function(x) shift(rleid(x) == max(rleid(x)))))] <- NA

<强>结果:

  C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 C11 C12 C13 C14 C15
1 12  3  3  4  5  6  7 NA NA  NA  NA  NA  NA  NA  NA
2  1  4  5  5  5  5  5  5  6   7   8  NA  NA  NA  NA
3  3  4  4  4  4 45 32 57 23  NA  NA  NA  NA  NA  NA

请注意,即使重复整数出现在每行中没有连接到最后重复序列的任何位置,这也是有效的。

数据:

df = structure(list(C1 = c(12L, 1L, 3L), C2 = c(3L, 4L, 4L), C3 = c(3L, 
5L, 4L), C4 = c(4L, 5L, 4L), C5 = c(5L, 5L, 4L), C6 = c(6L, 5L, 
45L), C7 = c(7L, 5L, 32L), C8 = c(7L, 5L, 57L), C9 = c(7L, 6L, 
23L), C10 = c(7L, 7L, 23L), C11 = c(7L, 8L, 23L), C12 = c(7L, 
8L, 23L), C13 = c(7L, 8L, 23L), C14 = c(7L, 8L, 23L), C15 = c(7L, 
8L, 23L)), .Names = c("C1", "C2", "C3", "C4", "C5", "C6", "C7", 
"C8", "C9", "C10", "C11", "C12", "C13", "C14", "C15"), class = "data.frame", row.names = c(NA, 
-3L))

答案 1 :(得分:1)

使用基础R,您可以像下面这样做 这是该函数的第三个版本,感谢@useR在某些用例中指出其他函数的错误结果。

fun <- function(x, n){
  r <- rle(x)
  n <- length(x)
  x[(n - r$lengths[length(r$lengths)] + 2):n] <- NA
  x
}

x <- c(12,3,3,4,5,6,7,7,7,7,7,7,7,7,7)
fun(x)
#[1] 12  3  3  4  5  6  7 NA NA NA NA NA NA NA NA

y <- c(12,7,7,4,5,6,7,7,7,7,7,7,7,7,7)
fun(y)
#[1] 12  7  7  4  5  6  7 NA NA NA NA NA NA NA NA

现在使用data.frame

dat[] <- t(apply(dat, 1, fun))
#  C1 C2 C3 C4 C5 C6 C7 C8 C9 C10 C11 C12 C13 C14 C15
#1 12  3  3  4  5  6  7 NA NA  NA  NA  NA  NA  NA  NA
#2  1  4  5  5  5  5  5  5  6   7   8  NA  NA  NA  NA
#3  3  4  4  4  4 45 32 57 23  NA  NA  NA  NA  NA  NA

数据。

dat <- read.csv(text = "
C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15
12,3,3,4,5,6,7,7,7,7,7,7,7,7,7
1,4,5,5,5,5,5,5,6,7,8,8,8,8,8
3,4,4,4,4,45,32,57,23,23,23,23,23,23,23
")

答案 2 :(得分:1)

数据:

$('#add')

代码:

df1 <- read.table(text='C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15
12,3,3,4,5,6,7,7,7,7,7,7,7,7,7
                  1,4,5,5,5,5,5,5,6,7,8,8,8,8,8
                  3,4,4,4,4,45,32,57,23,23,23,23,23,23,23', sep = ",", header = TRUE, stringsAsFactors = FALSE)

输出:

 apply(df1, 1, function(x) {
  x <- rle(x)
  len_x <- length(x$lengths)

  if( (x$lengths)[len_x] > 1 ){ # check for end sequence
    x <- list(lengths = c(x$lengths[-len_x], 1, x$lengths[len_x]- 1 ),
              values = c(x$values, NA))
  } 
  inverse.rle(x)
})

答案 3 :(得分:0)

在:

enter image description here

代码:

Sub marine()
    For i = 2 To 4
        For j = 15 To 2 Step -1
            If Cells(i, j).Value = Cells(i, j - 1).Value Then
                Cells(i, j).Value = "#N/A"
            Else
                Exit For
            End If
        Next j
    Next i
End Sub

之后:

enter image description here

答案 4 :(得分:0)

这只使用一个循环:

Sub nadup()

With Worksheets("Sheet5") 'change to your sheet
    Dim i As Long
    For i = 2 To 4
        Dim t As Long
        t = Application.Match(.Cells(i, 15), Range(i & ":" & i), 0)
        If t < 14 Then
            .Range(.Cells(i, t + 1), .Cells(i, 15)).Value = "N/A"
        ElseIf t = 14 Then
            .Cells(i, 15) = "N/A"
        End If
    Next i
End With



End Sub

答案 5 :(得分:0)

使用数组

Option Explicit

Public Sub ReplaceItems()
    Dim arr(), arr2(), i As Long, j As Long
    With ActiveSheet
        arr() = .Range("A1:O3").Value
        For i = LBound(arr, 1) To UBound(arr, 1)
            ReDim arr2(1 To UBound(arr, 2))
            For j = LBound(arr, 2) To UBound(arr, 2)
                If IsError(Application.Match(arr(i, j), arr2, 0)) Then
                    arr2(j) = arr(i, j)
                Else
                    Select Case arr(i, j)
                    Case 7, 8, 23
                    arr2(j) = "#N/A"
                    Case Else
                    arr2(j) = arr(i, j)
                    End Select
                End If
            Next
            .Range("A" & i).Resize(1, UBound(arr2)).Value = arr2
        Next i
    End With
End Su