multifunctionplotter 1.0.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,192 @@
1
+ import pandas as pd
2
+ import numpy as np
3
+ import os, sys, re, warnings
4
+
5
+ warnings.filterwarnings("ignore")
6
+
7
+ print("Data Manipulator")
8
+ print("=" * 70)
9
+ print("Program to slice, sort, merge, generate, append, delete, and show properties/props, data in a CSV file.")
10
+ print("=" * 70)
11
+
12
+ class MFPDataManipulator:
13
+ def __init__(self, datafile=None):
14
+ if datafile:
15
+ self.datafile = os.path.abspath(datafile) # Get absolute path
16
+ self.df = pd.read_csv(self.datafile).replace(np.nan, '', regex=True)
17
+ print ("Datafile loaded successfully.")
18
+ print(self.df)
19
+ else:
20
+ self.datafile = None
21
+ self.df = pd.DataFrame() # Initialize an empty DataFrame
22
+
23
+ def merge(self, other_file, on_column, how="inner"):
24
+ """
25
+ Merge the current DataFrame with another CSV file.
26
+ Args:
27
+ other_file (str): The file to merge with.
28
+ on_column (str): The column name to compare and merge on.
29
+ how (str): Merge strategy - 'inner', 'outer', 'left', or 'right'. Defaults to 'inner'.
30
+ Returns:
31
+ pd.DataFrame: The merged DataFrame.
32
+ """
33
+ try:
34
+ df_to_merge = pd.read_csv(other_file).replace(np.nan, '', regex=True)
35
+ self.df = pd.merge(self.df, df_to_merge, on=on_column, how=how)
36
+ return self.df
37
+ except FileNotFoundError:
38
+ print(f"File '{other_file}' not found.")
39
+ return self.df
40
+ except KeyError:
41
+ print(f"Column '{on_column}' not found in one of the files.")
42
+ return self.df
43
+
44
+ def slice(self, start, end):
45
+ start = int(start)
46
+ end = int(end)
47
+ self.df = self.df.iloc[start:end] # Update self.df
48
+ return self.df
49
+
50
+ def sort(self, col, order):
51
+ if order in ["ascending", "asc"]:
52
+ self.df = self.df.sort_values(by=[col], ascending=True) # Update self.df
53
+ elif order in ["descending", "desc"]:
54
+ self.df = self.df.sort_values(by=[col], ascending=False) # Update self.df
55
+ else:
56
+ raise ValueError("Invalid order. Use 'asc' or 'desc'.")
57
+ return self.df
58
+
59
+ def generate(self, xr, expr):
60
+ xr = xr.split(":")
61
+ x = np.linspace(int(xr[0]), int(xr[1]), int(xr[1]) - int(xr[0]) + 1)
62
+ y = eval(expr)
63
+ new_df = pd.DataFrame({"x": x, "y": y})
64
+ self.df = new_df # Replace any previous data frame with the new one
65
+ return self.df
66
+
67
+ def append(self, datafile):
68
+ df2 = pd.read_csv(datafile)
69
+ df2 = df2.replace(np.nan, '', regex=True)
70
+ self.df = pd.concat([self.df, df2]) # Update self.df
71
+ return self.df
72
+
73
+ def properties(self):
74
+ # Display the columns in a nice table with index
75
+ column_table = pd.DataFrame({
76
+ 'Index': range(len(self.df.columns)),
77
+ 'Column Name': self.df.columns
78
+ })
79
+ print("Column Index Table:")
80
+ print(column_table)
81
+
82
+ # Show NaN counts for each column
83
+ nan_counts = self.df.isnull().sum()
84
+ print("\nNaN Counts:")
85
+ print(nan_counts)
86
+
87
+ # Return the summary statistics
88
+ return self.df.describe()
89
+
90
+ def delete(self, targets):
91
+ # Check if the input targets are columns (strings) or rows (integers)
92
+ if all(target.strip().isnumeric() for target in targets.split(',')):
93
+ # If all targets are numeric, treat them as row indices
94
+ row_indices = [int(target.strip()) for target in targets.split(',')]
95
+ self.df = self.df.drop(index=row_indices) # Drop specified rows
96
+ else:
97
+ # Otherwise, treat them as column names
98
+ col_names = [target.strip() for target in targets.split(',')]
99
+ self.df = self.df.drop(columns=col_names) # Drop specified columns
100
+ return self.df
101
+
102
+ def modify(self, col, old_val, new_val):
103
+ self.df[col] = self.df[col].replace(old_val, new_val) # Update self.df
104
+ return self.df
105
+
106
+ def save(self, datafile):
107
+ directory = os.path.dirname(self.datafile)
108
+ save_path = os.path.join(directory, datafile)
109
+ self.df.to_csv(save_path, index=False) # Save the updated DataFrame
110
+ print(f"Data saved to {save_path}")
111
+
112
+ if __name__ == "__main__":
113
+ while True:
114
+ datafile = input("Enter the CSV file name (or press Enter to skip): ")
115
+ if datafile.strip():
116
+ try:
117
+ data_manipulator = MFPDataManipulator(datafile)
118
+ print("Datafile loaded successfully.")
119
+ except FileNotFoundError:
120
+ print(f"File '{datafile}' not found. Please try again.")
121
+ continue
122
+ else:
123
+ data_manipulator = MFPDataManipulator() # Create an instance with no file
124
+ print("No datafile loaded. You can generate data from scratch.")
125
+
126
+ while True:
127
+ action = input("Enter an action (properties/props, slice, sort, merge, generate/gen, append, delete/del, modify, save, or exit/q): ").lower()
128
+
129
+ if action == "generate" or action == "gen":
130
+ xr = input("Enter the range for x (e.g., 0:10): ")
131
+ expr = input("Enter the expression for y (e.g., 5*x**2/np.exp(x)): ")
132
+ print(data_manipulator.generate(xr, expr))
133
+
134
+ elif action == "merge":
135
+ if data_manipulator.df.empty:
136
+ print("No data available to merge.")
137
+ continue
138
+ other_file = input("Enter the file name to merge with: ")
139
+ on_column = input("Enter the column name to merge on: ")
140
+ how = input("Enter the merge type (inner, outer, left, right): ").lower()
141
+ print(data_manipulator.merge(other_file, on_column, how))
142
+
143
+ elif action == "slice":
144
+ if data_manipulator.df.empty:
145
+ print("No data available to slice.")
146
+ continue
147
+ start = input("Enter the start index: ")
148
+ end = input("Enter the end index: ")
149
+ print(data_manipulator.slice(start, end))
150
+
151
+ elif action == "sort":
152
+ if data_manipulator.df.empty:
153
+ print("No data available to sort.")
154
+ continue
155
+ order = input("Enter the order (asc/desc): ")
156
+ col = input("Enter the column name to sort by: ")
157
+ print(data_manipulator.sort(col, order))
158
+
159
+ elif action == "properties" or action == "props":
160
+ print(data_manipulator.properties())
161
+
162
+ elif action == "append":
163
+ file_to_append = input("Enter the file name to append: ")
164
+ print(data_manipulator.append(file_to_append))
165
+
166
+ elif action == "delete" or action == "del":
167
+ if data_manipulator.df.empty:
168
+ print("No data available to delete.")
169
+ continue
170
+ targets = input("Enter the column names or row indices to delete (comma-separated): ")
171
+ print(data_manipulator.delete(targets))
172
+
173
+ elif action == "modify":
174
+ if data_manipulator.df.empty:
175
+ print("No data available to modify.")
176
+ continue
177
+ col = input("Enter the column name to modify: ")
178
+ old_val = input("Enter the old value to replace: ")
179
+ new_val = input("Enter the new value: ")
180
+ print(data_manipulator.modify(col, old_val, new_val))
181
+
182
+ elif action == "save":
183
+ save_file = input("Enter the file name to save the data: ")
184
+ data_manipulator.save(save_file)
185
+ print(f"Data saved to {save_file}")
186
+
187
+ elif action == "exit" or action == "q":
188
+ print("Exiting the program.")
189
+ exit(0)
190
+
191
+ else:
192
+ print("Invalid action. Please try again.")