2009-10-27 32 views
64

Tôi có một khung dữ liệu lớn (14552 hàng bởi 15 cột) chứa dữ liệu thanh toán từ năm 2001 đến 2007. Tôi đã sử dụng sqlFetch để lấy dữ liệu 2008. Để thêm dữ liệu năm 2008 để các dữ liệu của 7 năm trước người ta sẽ làm như sauGắn thêm hàng vào một khung dữ liệu - vấn đề nhân tố

alltime <-rbind(alltime,all2008)

Thật không may mà tạo ra

nhắn Cảnh báo: trong [<-.factor (*tmp*, ri, giá trị = c (NA, NA, NA, NA, NA, NA, NA,: mức hệ số không hợp lệ, NA được tạo ra

Tôi đoán là vậy e là một số bệnh nhân mới có tên không có trong khung dữ liệu trước đó và do đó nó sẽ không biết mức độ để cung cấp cho nó. Một cột khác là tên của bác sĩ giới thiệu. Một bác sĩ giới thiệu mới sẽ gây ra cùng một vấn đề.

Cách R nhập dữ liệu và tự động tính toán số và cái gì không (và do đó làm cho nó là một yếu tố) là tuyệt vời - cho đến khi bạn phải thao tác thêm và sau đó nó trở thành một nỗi đau. Làm cách nào để khắc phục sự cố của tôi một cách thanh lịch?

+5

này là số lẻ. Yếu tố không nên gây ra điều này, trong sự giúp đỡ để 'rbind' được nói:" Các yếu tố có mức độ của họ mở rộng khi cần thiết "(R-2.9.2). Có lẽ bạn có thể kiểm tra chính xác cột nào gây ra điều này? – Marek

+1

Thật là một điểm tuyệt vời Marek! Tin nhắn cảnh báo làm tôi bối rối. Sau khi đọc nhận xét của bạn, tôi đã quay trở lại để khám phá dữ liệu của mình. Tất cả dữ liệu mới dường như ở đó và các cấp bổ sung đã được thêm vào. Ở giai đoạn này, tôi có thể bỏ qua nó như một lời cảnh báo cần được bỏ qua - đó là một thói quen nguy hiểm để xâm nhập vào (kể từ đó người ta phải giữ một cơ sở dữ liệu trong đầu cảnh báo để được thực hiện nghiêm túc và cảnh báo bị bỏ qua). Làm cách nào để tìm ra thông điệp cảnh báo đến từ đâu? – Farrel

Trả lời

30

Có thể do sự không phù hợp của các loại trong hai data.frames.

Trước hết các loại kiểm tra (lớp). Để mục đích chẩn đoán làm điều này:

new2old <- rbind(alltime, all2008) # this gives you a warning 
old2new <- rbind(all2008, alltime) # this should be without warning 

cbind(
    alltime = sapply(alltime, class), 
    all2008 = sapply(all2008, class), 
    new2old = sapply(new2old, class), 
    old2new = sapply(old2new, class) 
) 

tôi hy vọng có thể là một hàng trông giống như:

  alltime all2008 new2old old2new 
...   ...  ...  ...  ... 
some_column "factor" "numeric" "factor" "character" 
...   ...  ...  ...  ... 

Nếu vậy thì giải thích: rbind không kiểm tra các loại kết hợp. Nếu bạn phân tích rbind.data.frame mã thì bạn có thể thấy rằng đối số đầu tiên được khởi tạo các loại đầu ra. Nếu trong loại data.frame đầu tiên là một yếu tố, sau đó đầu ra data.frame cột là yếu tố với các cấp unique(c(levels(x1),levels(x2))). Nhưng khi trong cột data.frame thứ hai không phải là yếu tố thì levels(x2)NULL, vì vậy các cấp không mở rộng.

Điều đó có nghĩa là dữ liệu đầu ra của bạn sai! Có NA 's thay vì giá trị đích thực

Tôi giả sử rằng:

  1. bạn tạo cho bạn dữ liệu cũ với một R phiên bản/RODBC để loại được tạo ra với các phương pháp khác nhau (cài đặt khác nhau - separator thập phân có thể)
  2. có dữ liệu NULL hoặc một số dữ liệu cụ thể trong cột có vấn đề, ví dụ: ai đó thay đổi cột dưới cơ sở dữ liệu.

Giải pháp:

tìm cột sai và tìm lý do tại sao của nó sai và cố định. Loại bỏ nguyên nhân không phải triệu chứng.

+1

Yip. Bạn nói đúng. trong một khung dữ liệu, một lớp của cột là một yếu tố và một cột khác là một số. Điều đó đã làm rối tung mọi thứ. Tôi đã chuyển đổi số thành một yếu tố và tất cả đều OK. Cảm ơn sự hướng dẫn của bạn. Có một số khác biệt khác. Ví dụ, sự khác biệt nhân vật yếu tố không làm mọi thứ rối tung lên. – Farrel

+0

Bạn có quyền về yếu tố nhân vật, một nơi nào đó trong mã tôi thấy rằng các cấp cho sự kết hợp này sẽ là 'duy nhất (c (cấp (x1), x2)) '. Một điều: yếu tố nhân tố kết hợp dẫn đến yếu tố, nhân tố kết hợp với nhân vật. Vì vậy, nó tốt hơn khi các loại phù hợp. – Marek

26

Cách "dễ dàng" chỉ đơn giản là không đặt chuỗi của bạn làm yếu tố khi nhập dữ liệu văn bản.

Lưu ý rằng các chức năng read.{table,csv,...} có tham số stringsAsFactors, theo mặc định được đặt thành TRUE. Bạn có thể đặt số này thành FALSE trong khi nhập và rbind -ing dữ liệu của mình.

Nếu bạn muốn đặt cột là yếu tố ở cuối, bạn cũng có thể làm điều đó.

Ví dụ:

alltime <- read.table("alltime.txt", stringsAsFactors=FALSE) 
all2008 <- read.table("all2008.txt", stringsAsFactors=FALSE) 
alltime <- rbind(alltime, all2008) 
# If you want the doctor column to be a factor, make it so: 
alltime$doctor <- as.factor(alltime$doctor) 
+1

Tôi tin rằng bạn có một số lỗi đánh máy trong câu trả lời của bạn ... – griffin

+1

Rất tiếc, cảm ơn bạn đã chỉ ra điều đó. Đã sửa lỗi (tôi nghĩ). –

4

Như đã đề cập trong các câu trả lời trước, đọc các cột như nhân vật và làm việc chuyển đổi các yếu tố sau rbind. SQLFetch (Tôi giả định RODBC) cũng có các đối số stringsAsFactors hoặc as.is để kiểm soát việc chuyển đổi ký tự. Giá trị được phép là dành cho read.table, ví dụ: as.is=TRUE hoặc một số số cột.

3

Tôi đã gặp vấn đề tương tự với loại không phù hợp, đặc biệt là với các yếu tố. Tôi phải dán hai bộ dữ liệu tương thích khác nhau lại với nhau.

Giải pháp của tôi là chuyển đổi các yếu tố trong cả hai khung dữ liệu thành "ký tự". Sau đó, nó hoạt động như một nét duyên dáng :-)

convert.factors.to.strings.in.dataframe <- function(dataframe) 
    { 
     class.data <- sapply(dataframe, class) 
     factor.vars <- class.data[class.data == "factor"] 
     for (colname in names(factor.vars)) 
     { 
      dataframe[,colname] <- as.character(dataframe[,colname]) 
     } 
     return (dataframe) 
    } 

Nếu bạn muốn xem các loại trong hai dataframes của bạn chạy (tên thay đổi var):

cbind("orig"=sapply(allSurveyData, class), 
      "merge" = sapply(curSurveyDataMerge, class), 
      "eq"=sapply(allSurveyData, class) == sapply(curSurveyDataMerge, class) 
    ) 
+0

chức năng rất hữu ích để có, cảm ơn. – PatrickT

+3

'mydf [sapply (mydf, is.factor)] <- lapply (mydf [sapply (mydf, is.factor)], as.character)' có vẻ như là một cách tiếp cận đơn giản hơn. – A5C1D2H2I1M1N2O1R2T1

7

1) tạo ra các khung dữ liệu với bộ stringsAsFactor thành FALSE. Điều này sẽ giải quyết vấn đề yếu tố

2) sau đó không sử dụng rbind - nó làm lộn xộn tên cột nếu khung dữ liệu trống. chỉ đơn giản là làm theo cách này:

df[nrow(df)+1,] <- c("d","gsgsgd",4) 

/

> df <- data.frame(a = character(0), b=character(0), c=numeric(0)) 

> df[nrow(df)+1,] <- c("d","gsgsgd",4) 

Warnmeldungen: 
1: In `[<-.factor`(`*tmp*`, iseq, value = "d") : 
    invalid factor level, NAs generated 
2: In `[<-.factor`(`*tmp*`, iseq, value = "gsgsgd") : 
    invalid factor level, NAs generated 

> df <- data.frame(a = character(0), b=character(0), c=numeric(0), stringsAsFactors=F) 

> df[nrow(df)+1,] <- c("d","gsgsgd",4) 

> df 
    a  b c 
1 d gsgsgd 4 
0

đây là một chức năng để lấy tên hàng chung của 2 khung dữ liệu và làm một rbind nơi chúng tôi về cơ bản tìm ra lĩnh vực mà là những yếu tố, thêm các yếu tố mới sau đó làm rbind. Điều này cần chăm sóc của bất kỳ vấn đề yếu tố:

rbindCommonCols < -function (x, y) {

commonColNames = intersect(colnames(x), colnames(y)) 
x = x[,commonColNames] 
y = y[,commonColNames] 

colClassesX = sapply(x, class) 
colClassesY = sapply(y, class) 
classMatch = paste(colClassesX, colClassesY, sep = "-") 
factorColIdx = grep("factor", classMatch) 

for(n in factorColIdx){ 
    x[,n] = as.factor(x[,n]) 
    y[,n] = as.factor(y[,n]) 
} 

for(n in factorColIdx){ 
    x[,n] = factor(x[,n], levels = unique(c(levels(x[,n]), levels(y[,n])))) 
    y[,n] = factor(y[,n], levels = unique(c(levels(y[,n]), levels(x[,n])))) 
} 

res = rbind(x,y) 
res 

}

Các vấn đề liên quan