1

httrいくつかのデータフレームがあり、各データフレームの行をループして、パッケージを使用して SMS メッセージを送信するなど、何かをしたいとしましょう。いくつかのループを作成することはできますが、答えは「ループを使用しないでください!」だと思います。

df1 <- data.frame(A=1:10, B=2:11, C=3:12) # imagine these columns hold words and phone numbers
df2 <- data.frame(A=4:13, B=5:14, C=6:15)

# loop for df1
for (n in 1:nrow(df1)) { # imagine that each row is a person
  # get details for each person (row)
  sms1 <- df1$A[n]
  sms2 <- df1$B[n]
  sms3 <- df1$C[n]
  # create personalized message to send
  sms <- paste(sms1, sms2, sms3, sep=" ")
  # here I would use the POST() function of httr to send a personalized SMS to each person, but that is not important
}

# loop for df2
for (n in 1:nrow(df1)) {
  sms1 <- df2$A[n]
  sms2 <- df2$B[n]
  sms3 <- df2$C[n]
  sms <- paste(sms1, sms2, sms3, sep=" ")
  # here I would use the POST() function of httr to send a personalized SMS, but that is not important
}

しかし、私が本当にやりたいことは、各データフレームをループする外側のループを作成することです。何かのようなもの:

dfs <- c("df1", "df2")
# loop over dfs
for (d in dfs) {
  for (n in 1:nrow(d)) {
    sms1 <- d$A[n]
    sms2 <- d$B[n]
    sms3 <- d$C[n]
    sms <- paste(sms1, sms2, sms3, sep=" ")
    # here I would use the POST() function of httr to send a personalized SMS, but that is not important
  }
}

しかし、私はこれがうまくいかないことを知っています。My dinはorsms1 <- d$A[n]とは読みません。sms1 <- df1$A[n]sms1 <- df2$A[n]

このループを行う方法はありますか?さらに良いことに、正しい適用方法は何ですか?

アップデート:

以下は、パーソナライズされたメッセージをすべての人 (行) に送信するために、両方のデータフレームのすべての行に対して実行する必要がある POST ステップの例です。

# let's say that sms3 in my example is a phone number
# let's also say that I define the following objects once outside of the loop:
  # url, username, password, account, source, network

# when I paste together the following objects, I get string that is formatted for my API gateway. 
send <- paste0(url, username, password, account, source, sms3, 
                 sms, network)
POST(send)

元の投稿のコメントで述べたように、これはループに入ります。

# remove these paste steps from the loops as recommended in the answers
df1$sms <- paste(df2$A, df2$B)
df2$sms <- paste(df2$A, df2$B)

dfs <- c("df1", "df2")

# loop over dfs
for (d in dfs) {
  for (n in 1:nrow(d)) {
    sms3 <- d$C[n] # to get phone number
    send <- paste0(url, username, password, account, source, sms3, sms, network)
    POST(send)
  }
}
4

2 に答える 2

3

paste要素をまとめて各行をループする必要はありません。paste代わりに、データ フレームごとに 1 回だけ呼び出すことができます。

df1$sms <- paste(df1$A, df1$B, df1$C)

df1$send次に、これを取得して再度呼び出して作成するか、特定のニーズに応じてpaste1 つだけを使用できます。paste

に必要なものがすべて揃ったので、各要素df1$sendを呼び出すだけです。はベクトル化されていないため、何らかの方法で要素を反復処理する必要があります。例えば:POSTPOST

sapply(df1$send, POST)

に対してこれをもう一度行うこともできますdf2が、別の方法は、データ フレームのリストを作成し、それをループして、paste各データ フレームに対して同じ操作を行うことです。例えば:

my.dfs <- list(df1, df2)
for (df in my.dfs) {
  df$sms <- paste(df$A, df$B, df$C)
  ...
  sapply(df$send, POST)
}

(最初に行ったように、名前の文字列をループして、各文字列に対応する実際のオブジェクトを取得することもできdf <- get(d)ます: 。しかし、これを好む理由はここにはありません。)

さらに良い方法は、df1df2を 1 つのデータ フレームに結合することです。2 つのグループを区別する列を作成できます。そうすれば、1 つのデータ フレームでのみ実行する必要がありpasteますPOST

comprehensive.df$sms <- paste(comprehensive.df$A, comprehensive.df$B, comprehensive.df$C)
...
sapply(comprehensive.df$send, POST)

これを行う方法は、データ フレームの違いによって異なります。それらがわずかに異なる場合は、不足している列を処理するrbind.fillfromを使用できます。plyr列名などが異なる場合は、共通の列を抽出して名前を変更できます。ただ、本題に入る前に掃除と合体をしておけば、やっていることはより明確になると思います。

forループを使用しても問題ありません。実際、 のソースを見ると、ループapplyが使用されていることがわかります。for本当のapply利点は、 を使用することではなく、上記の で行ったように、オブジェクト全体を関数に渡すことによってベクトル化を利用することですpaste。これはより読みやすく (1 つの単純な行であるため)、おそらくパフォーマンスが向上します (関数を 1 回しか呼び出さないため)。

于 2013-07-03T12:30:19.813 に答える