您的第二列是(我认为)一个字符向量。 strsplit,正如它在文档中提到的 (?strsplit) 返回一个列表。在我们了解为什么您的具体情况发生之前,一些一般性建议:
- 创建一个新列而不是替换现有列。这样做的额外好处是不会丢失原始值。
- 仅用同一类的新值替换列中的值(例如,字符替换字符,整数替换整数)。
所以我建议添加一个新的拆分值列:
letters[["splits"]] <- strsplit(letters[[2]], split = "|", fixed = TRUE)
您现在有一个列表列,该列的每一行都有一个由原始值拆分的字母组成的向量。
您的问题发生的原因
让我们剖析赋值语句:
letters[i,2] <- strsplit(letters[i,2], split = "[|]")
<- 的左侧是letters[i, 2],也就是data.frame。 data.frame 将其所有数据存储在一个列表中。 R 允许我们使用这个事实,尤其是在赋值中。我们可以添加或替换列,就像添加或替换列表中的项目一样。
# This...
letters[, "one"] <- 1
letters[, "two"] <- 2
# is effectively the same as this
letters[, c("one", "two")] <- list(1, 2)
在-> 的右侧,我们调用了strsplit(),它返回一个list。如上例所示,如果将列表分配给data.frame 的子集,它将被强制转换为data.frame 本身。列表的每个元素都将被视为一列。所以,任务是这样进行的:
- 如果
letters[i,2] 是"A|B|C|D|E",那么strsplit(letters[i,2], split = "[|]") 是list(c("A", "B", "C", "D", "E"))。
- 分配检查双方,并将
data.frame 视为“更高”类型,因此它将列表强制为data.frame。右侧现在实际上是 data.frame(c("A", "B", "C", "D", "E"))。
- 现在它尝试将具有 1 列和 5 行 的
data.frame 分配给具有 1 列和 1 行 的子集。这些尺寸不匹配,因此它会从右侧(仅第一行)获取尽可能多的内容并警告您发生的情况。
为什么建议的作业有效
那为什么没有强制呢?
letters[["splits"]] <- strsplit(letters[[2]], split = "|", fixed = TRUE)
左侧使用[[ 子集(将data.frame 视为列表)添加或替换"splits" 列。所以从来没有强制执行过。
此外,data.frame 可以将list 作为列,就像list 可以将list 作为元素一样。 data.frame 列只需要满足两件事:
- 它必须是一个向量。
- 其长度必须等于
data.frame 中的行数(必要时尝试回收)。
list 是一种向量。并且strsplit() 返回一个与其输入长度相同的列表,因此满足两个条件。