3

95列のデータフレームがあり、下部のスニペットのように、単純な正規表現を使用してそれらの多くの名前をバッチ変更したいのですが、そのような行は最大30行あります。検索正規表現に一致しないその他の列は、そのままにしておく必要があります。

****例:names(tr)= c('foo'、'bar'、'xxx_14'、'xxx_2001'、'yyy_76'、'baz'、'zzz_22'、...)****

私は25gsub()の壁から始めました-粗雑ですが効果的です:

names(tr) <- gsub('_1$',    '_R', names(tr))
names(tr) <- gsub('_14$',   '_I', names(tr))
names(tr) <- gsub('_22$',   '_P', names(tr))
names(tr) <- gsub('_50$',   '_O', names(tr))
... yada yada

@Joshua:mapplyは機能しません。ベクトル化するのはもっと複雑で、不可能であることがわかります。names(tr)には他の列が含まれており、これらのパターンが発生した場合、定義した正確な順序は言うまでもなく、すべてが発生したとは限りません。したがって、2を試してください:

pattern <- paste('_', c('1','14','22','50','52','57','76','1018','2001','3301','6005'), '$', sep='')
replace <- paste('_', c('R','I', 'P', 'O', 'C', 'D', 'M', 'L',   'S',   'K',   'G'),         sep='')
do.call(gsub, list(pattern, replace, names(tr)))
Warning messages:
1: In function (pattern, replacement, x, ignore.case = FALSE, perl = FALSE,  :
  argument 'pattern' has length > 1 and only the first element will be used
2: In function (pattern, replacement, x, ignore.case = FALSE, perl = FALSE,  :
  argument 'replacement' has length > 1 and only the first element will be used

誰かが私のためにこれを修正できますか?


編集:私はこの主題に関するSOとRのドキュメントを1日以上読んだのですが、何も見つかりませんでした...それを投稿すると、「[r]翻訳テーブル」を検索することを考え、xlateを見つけます。これは、 grep / sub/gsubのドキュメントのどこにも記載されていません。

  1. base/gsubfn/data.table検索と置換の指示を1つ書くことができるものなどはありますか?(辞書や翻訳テーブルのように)

  2. 私の不格好な構文をtrへの参照による呼び出しになるように改善できますか?(df全体の一時コピーを作成してはいけません)


EDIT2:読んだ後の私の最善の努力は:

ディクショナリアプローチ(xlate)は部分的な答えかもしれませんが、正規表現はターミナル(たとえば、「_ 14 $」)でなければならないため、これは単純な変換テーブル以上のものです。

gsub()またはstrsplit()を使用して'_'で分割し、最後のコンポーネントでxlate変換を実行してから、それらを一緒にpaste()することができます。よりクリーンな1/2行のイディオムを探しています。

または、gsub()の壁を使用します。

4

3 に答える 3

4

の壁はgsub常に。に置き換えることができますfor-loop。そして、あなたはそれを関数として書くことができます:

renamer <- function(x, pattern, replace) {
    for (i in seq_along(pattern))
            x <- gsub(pattern[i], replace[i], x)
    x
}

names(tr) <- renamer(
     names(tr),
     sprintf('_%s$', c('1','14','22','50','52','57','76','1018','2001','3301','6005')),
     sprintf('_%s' , c('R','I', 'P', 'O', 'C', 'D', 'M', 'L',   'S',   'K',   'G'))
)

そして、私はこの種の文字列を作成sprintfするよりも便利だと思いました。paste

于 2012-05-04T22:21:17.023 に答える
1

質問はブームの前にありますが、これはのオプションでtidyverse簡単に解決できます。c(pattern1 = replacement1)stringr::str_replace_all

tr <- data.frame("whatevs_1" = NA, "something_52" = NA)

tr
#>   whatevs_1 something_52
#> 1        NA           NA

patterns <- sprintf('_%s$', c('1','14','22','50','52','57','76','1018','2001','3301','6005'))
replacements <- sprintf('_%s' , c('R','I', 'P', 'O', 'C', 'D', 'M', 'L',   'S',   'K',   'G'))
                        
names(replacements) <- patterns

names(tr) <- stringr::str_replace_all(names(tr), replacements)

tr
#>   whatevs_R something_C
#> 1        NA          NA

そしてもちろん、この特定のケースは恩恵を受けることができますdplyr

dplyr::rename_all(tr, stringr::str_replace_all, replacements)
#>   whatevs_R something_C
#> 1        NA          NA
于 2021-01-04T23:09:34.887 に答える
0

do.call()ほぼそれを使用して、それは異なる引数の長さに反対します。リスト上の要素に関数を適用する場合のように、do.call()内部にネストする必要があると思います。apply()

しかし、部分的なdo.call()オーバーパターンと交換が必要です。

これはすべて、たるんだコードの場合、gsub(...、fixed = TRUE)の壁をより効率的なイディオムのように見せ始めています。

pattern <- paste('_', c('1','14','22','50'), '$', sep='')
replace <- paste('_', c('R','I', 'P', 'O'),       sep='')
do.call(gsub, list(pattern, replace, names(tr)))
Warning messages:
1: In function (pattern, replacement, x, ignore.case = FALSE, perl = FALSE,  :
  argument 'pattern' has length > 1 and only the first element will be used
2: In function (pattern, replacement, x, ignore.case = FALSE, perl = FALSE,  :
  argument 'replacement' has length > 1 and only the first element will be used
于 2012-05-04T21:11:01.563 に答える