2016-07-17 16 views
0

Census APIを使用して特定のテーブルをダウンロードし、データフレームに保存しようとしています。私はデータのダウンロードに成功しました。私は呼び出しのために適切なURLを集めて、次に 'rjson'というパッケージを使ってそのURLをリストに読みました。例:R:リストのリストをデータフレームに変換する(センサスデータ)

library(rjson)  

get <- c("B19081_002M")          # create vector of vars 
datafile <- "http://api.census.gov/data/2009/acs5?"   # ACS 05-09 
get <- paste0("get=NAME,", paste(get, collapse = ','))  # variables 
geo <- "for=county:*"          # all counties 
api_key <- "key=KEYHERE"          # API key 
url <- paste0(datafile, paste(get, geo, api_key, sep = "&")) # creates url 
data <- fromJSON(file = url)         # read into R 

# To see an example of a problematic observation 
# (this should return "Hinsdale County, Colorado") 

data[[273]] 

ただし、これをデータフレームに変換するのは難しいです。 fromJSON()関数はリストオブジェクトを作成します。ほとんどの場合、リストオブジェクトの要素は、各空間単位(例えば、上記の例ではcounty)のchrベクトルであり、ベクトルはテーブル情報と関連するメタデータを含む。この場合、以下の作業例のアプローチを使用して、リストをデータフレームに変換します。ここで、各行は異なる空間単位であり、各列は異なる変数です。

# Create fake data 
x1 <- seq(1:5) 
x2 <- rep(5,5) 
l1 <- list(x1,x2) 

# Convert to df 
cols_per_row <- length(unlist(l1[1])) 
test1 <- data.frame(matrix(unlist(l1), byrow = TRUE, ncol = cols_per_row)) 

print(test1) # success! 

X1 X2 X3 X4 X5 
1 1 2 3 4 5 
2 5 5 5 5 5 

しかし、私は(私はAPIから取得したさまざまなテーブルを含めていますので、発生する)リストで、リストのオブジェクトと同じアプローチを使用する場合、私はエラーが表示されます。

# Create fake data 
x1 <- seq(1:5) 
x2 <- rep(5,5) 
x3 <- list(1,2,3,4,NULL) 
l2 <- list(x1,x2,x3) 

# Produces an error 
cols_per_row <- length(unlist(l2[1])) 
test2 <- data.frame(matrix(unlist(l2), byrow = TRUE, ncol = cols_per_row)) 

Warning message: 
In matrix(unlist(l2), byrow = TRUE, ncol = cols_per_row) : 
data length [14] is not a sub-multiple or multiple of the number of columns [5] 

は誰もいこのための解決策がありますか?

  • サブリストは、変数の1つがNULL値を持つ場合にのみ表示されることに気付きました。
  • メインリストの要素もリストである場合、サブリストの長さは、ベクトルであるメインリストの要素のベクトルの長さに等しくなります。私はfromJSONと、これは簡単になるかもしれない歓迎代替手段を使用する必要はありません

ノート

  • これを達成するために 'acs'パッケージを使用したくないので、その使用を提案しないでください。私はこの問題に対処する方法を学ぼうとしています。
+0

'as.data.frame(do。コール(cbind、l2)) 'は典型的なものです(ただし、偉大ではありませんが、タイプを失うでしょう)。 'purrr'はリストを扱うのに便利です。あなたは 'l2%> setNames(make.names(seq_along()))%>%at_depth(2、〜.x%||%NA)%>%map_df(unlist)'のようなことをすることができます。最も優雅なバージョンではありません。 – alistaire

答えて

0

多分これはあなたが後にしているものです。

simplify2array(l2) 

EDIT:

上記のソリューションが動作しませんでした。代替として、私はNAでNULL値を置き換えます:

# Function to replace NULL values to NA values inside a list 
listNull2Na <- function(l) sapply(l, function(x) ifelse(is.null(x), NA, x)) 

# Substitute NULL values in your list and get matrix: 
l2 <- sapply(l2, listNull2Na) 
+0

私はそれが実際のデータでは動作しないと思います。少なくとも私のテストでは(奇妙な形になった - 1つの次元をカットし、3,222列を与えた)。もし私が間違っているなら、私を訂正してください、OP。 –

+0

@ Hack-R悲しいことに私は実際のデータを持っていないので、テストすることはできません。 OPが提供するおもちゃデータに取り組んでいます... @ user3614648この関数は 'sapply()'によって内部的に使われています。しかし、 'simplify2array'とタイプすることでコードを調べることができます。これは、やっていることと多少似ていますが、データのリストを解除し、それを適切な配列に配置します。あなたのケースでは、各サブリストの長さが同じであるために動作します。参照: 'lengths(l2)'(NULLの場合でも)長さが違うとうまくいかないかもしれません。 –

+0

@ user3614648参照してください。たぶんあなたは間違っていることを詳しく説明したり、これがあなたのためにはうまくいかない単純なケースを追加したりすることができますか? –

1

私があなたに本当のクエリを使用してハックを与える:

tmp <- data.frame(matrix(ncol=4)) 

for(i in 1:length(data)){ 
    if(length(t(unlist(data[i]))) == 4){ 
    tmp[i,] <- t(unlist(data[i])) 
    } else{ 
    cat("Row number ", i, "has an abnormal length \n") 
    } 
} 
Row number 273 has an abnormal length 
Row number 550 has an abnormal length 
Row number 1900 has an abnormal length 
Row number 2733 has an abnormal length 
Row number 2737 has an abnormal length 
Row number 2753 has an abnormal length 
head(tmp) 
1        NAME B19081_002M state county 
2  Aleutians East Borough, Alaska  8469 02 013 
3 Aleutians West Census Area, Alaska  7691 02 016 
4  Anchorage Municipality, Alaska   920 02 020 
5   Bethel Census Area, Alaska  2414 02 050 
6  Bristol Bay Borough, Alaska  9635 02 060 
のみ

のうち6> 3000を長さが異常ですが、それらの行を救助したい場合は、別の行を追加して欠落値をプレースホルダで埋めることで可能です。

最後に、最初の行がヘッダーなので、data.frameのcolnamesに書き込むことができます。

+0

これは、リストの問題のある要素を識別するのに便利なハックです。それは問題自体に対する答えではありませんが、私はそれが役に立つのでアップアップします。 注:オブジェクトが返されたときに、変数名が最初の行に表示されている理由(これは私のアプリケーションではこれを自動化しています)もやや不思議です。 – user3614648

関連する問題