循环遍历数据框,该数据框基于其他列的条件和值生成输出

时间:2015-07-30 00:41:46

标签: r

我的df的简短版本如下:

A <- c(10,50,50,10,60,70,50,20,60,10)
B <- c(0,3,2,4,1,3,5,1,1,2)
df<- data.frame(A,B)
df
A   B   
10  0
50  3
50  2
10  4
60  1
70  3
50  5
20  1
60  1
10  2

我想根据A列的某些条件和B列中的值生成输出C.

条件:

    当A <1时,
  1. C = 0。 50或A&#34;刚刚成为&#34; &gt; = 50
  2. 当L [n + 1]和B [n]都> = 50 时,
  3. C = abs(B [n + 1] - B [n])

    以下是C列中我想要的一个例子:

    A   B   C   Explaination
    10  0   0    A <50, so C=0
    50  3   0    A just becomes >= 50, so C is still 0
    50  2   1    We have two consecutive A >= 50, so C = abs(2-3) = 1
    10  4   0    A <50, so C=0
    60  1   0    A just becomes >= 50, so C is still 0
    70  3   2    We have two consecutive A >= 50, so C = abs(3-1) = 2
    50  5   2    consecutive rows with A >= 50, so C = abs(5-3) = 2
    20  1   0    A <50, so C=0
    60  1   0    A just becomes >= 50, so C is still 0
    10  2   0    A <50, so C=0
    

2 个答案:

答案 0 :(得分:1)

这是一个选项,虽然逻辑有点啰嗦:

df$C <- ifelse(df$A < 50 | (df$A >= 50 & c(0, head(df$A, -1)) < 50) ,
               0, c(NA, abs(diff(df$B))))

说明:

  • 我从ifelse(df$A < 50, 0, c(NA, abs(diff(df$B))))开始。如果A < 50,则给出0,否则B的差异(diff(B)是一个短于B的元素,所以我在NA上加A前)。
  • 但是,这并不能解释c(0, head(df$A, -1))首次超过50的情况,其中值仍应为0。注意2:end只是A列的元素0,前面有A - 它是df$A >= 50的“上一个”值。因此,如果< 50和之前的值为import javafx.application.Application; import javafx.beans.property.IntegerProperty; import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.control.SelectionMode; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.layout.BorderPane; import javafx.scene.layout.VBox; import javafx.scene.text.Text; import javafx.stage.Stage; public class TableCopyPasteCellsDemo extends Application { private final ObservableList<Person> data = FXCollections.observableArrayList(new Person("Jacob", "Smith", 18), new Person("Isabella", "Johnson", 19), new Person("Ethan", "Williams", 20), new Person("Michael", "Brown", 21)); public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) { stage.setWidth(500); stage.setHeight(550); // create table columns TableColumn<Person, String> firstNameCol = new TableColumn<Person, String>("First Name"); firstNameCol.setMinWidth(100); firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName")); // firstNameCol.setVisible(false); // hide column for testing view/model indices TableColumn<Person, String> lastNameCol = new TableColumn<Person, String>("Last Name"); lastNameCol.setMinWidth(100); lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName")); TableColumn<Person, Integer> ageCol = new TableColumn<Person, Integer>("Age"); ageCol.setMinWidth(60); ageCol.setCellValueFactory(new PropertyValueFactory<Person, Integer>("age")); TableView<Person> table = new TableView<>(); table.setPlaceholder(new Text("No content in table")); table.setItems(data); table.getColumns().addAll(firstNameCol, lastNameCol, ageCol); final VBox vbox = new VBox(); vbox.setSpacing(5); vbox.setPadding(new Insets(10, 10, 10, 10)); BorderPane borderPane = new BorderPane(); borderPane.setCenter(table); vbox.getChildren().addAll(borderPane); vbox.getChildren().add( new Label( "Select cells and press CTRL+C. Paste the data into Excel or Notepad")); Scene scene = new Scene(vbox); stage.setScene(scene); stage.show(); // enable multi-selection table.getSelectionModel().setCellSelectionEnabled(true); table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); // enable copy/paste TableUtils.installCopyPasteHandler(table); } public static class Person { private final StringProperty firstName; private final StringProperty lastName; private final IntegerProperty age; private Person(String fName, String lName, Integer age) { this.firstName = new SimpleStringProperty(fName); this.lastName = new SimpleStringProperty(lName); this.age = new SimpleIntegerProperty(age); } public final StringProperty firstNameProperty() { return this.firstName; } public final java.lang.String getFirstName() { return this.firstNameProperty().get(); } public final void setFirstName(final java.lang.String firstName) { this.firstNameProperty().set(firstName); } public final StringProperty lastNameProperty() { return this.lastName; } public final java.lang.String getLastName() { return this.lastNameProperty().get(); } public final void setLastName(final java.lang.String lastName) { this.lastNameProperty().set(lastName); } public final IntegerProperty ageProperty() { return this.age; } public final int getAge() { return this.ageProperty().get(); } public final void setAge(final int age) { this.ageProperty().set(age); } } } ,那么这是我们第一次超过50,我们应该得到值0.

我相信还有其他方法可以做到。

答案 1 :(得分:0)

library(dplyr)
df%>%mutate(C=ifelse(A<50,0,(ifelse(A>=50 & lag(A)>=50,abs(B-lag(B)),0))))