🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

2239閲覧

python csv 最小値計算(条件付き)

退会済みユーザー

退会済みユーザー

総合スコア0

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2019/10/18 09:15

編集2019/10/18 09:18

pythonを用いて二つのcsvファイルから最小値を見つけ、見つけた最小値同士を足し算したスクリプトが以下となります。

import pandas as pd

filename = pd.read_csv('OD(1).csv', encoding="SHIFT-JIS")

listA = []
listB = []
listC = []

listA = filename['OriginID']
listB = filename['DestinationID']
listC = filename['Shape_Length']

min_ik=99999

leng = len(listA)
leng = len(listB)

for n in range(leng):
if listC[n]<min_ik:
min_ik=listC[n]
num = n
print("最小値は"+str(min_ik)+"であり"+"この時の経路は"+str(listA[num])+"-"+str(listB[num]))

filename = pd.read_csv('OD(2).csv', encoding="SHIFT-JIS")
listD = []
listE = []
listF = []

listD = filename['OriginID']
listE = filename['DestinationID']
listF = filename['Shape_Length']

min_kj=99999

leng = len(listD)
leng = len(listE)

for n in range(leng):
if listF[n]<min_kj:
min_kj=listF[n]
num = n
print("最小値は"+str(min_kj)+"であり"+"この時の経路は"+str(listD[num])+"-"+str(listE[num]))

lik = min_ik
lkj = min_kj

lij = lik + lkj
print(lij)

OD(1).csvの中身は以下の通り
[OriginID,DestinationID,Shape_Length][1,A,10][2,B,15][3,A,5]

OD(2).csvの中身は以下の通り
[OriginID,DestinationID,Shape_Length][A,X,100][A,Y,50][B,Z,30]

上記の内容だと
最小値は5でありこの時の経路は3-A
最小値は30でありこの時の経路はB-Z
35
となります。

これに条件としてOD(1).csvのDestinationIDとOD(2).csvのOriginIDが同じもの同士を計算し、最小値を出したいとしたときに(if分を使用することになるかと思いますが)どのような文を追加することで、得たい結果になりますでしょうか。

具体的には、
OD(2).csvの[B,Z,30]は固定で、OD(1).csvの中の[ ,B, ]というものの中から最小値を出したいと考えております。
今回であれば
最小値は15でありこの時の経路は2-B
最小値は30でありこの時の経路はB-Z
45
という結果を得たいです。

基本的な内容で申し訳ございませんが、ご教授いただけたら幸いです。
よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

在、pandas をCSVの読み込みのみで使用しているようですが、この手の処理を行うのであれば、全ての処理をpandas上で行った方が楽です。

Python

1import pandas as pd 2 3df1 = pd.DataFrame([[1,'A',10],[2,'B',15],[3,'A',5]], 4 columns=['OriginID','DestinationID','Shape_Length']) 5 6df2 = pd.DataFrame([['A','X',100],['A','Y',50],['B','Z',30]], 7 columns=['OriginID','DestinationID','Shape_Length']) 8 9df = pd.merge(df1, df2, left_on='DestinationID', right_on='OriginID', how='outer', suffixes=('_1st', '_2nd')) 10df['Total'] = df['Shape_Length_1st'] + df['Shape_Length_2nd'] 11min_row = df.loc[df['Total'].idxmin()] 12print(f"最小値は{min_row['Total']}であり、この時の経路は {min_row['OriginID_1st']} - {min_row['DestinationID_1st']} - {min_row['DestinationID_2nd']}") 13 14# 最小値は45であり、この時の経路は 2 - B - Z

やっている処理を頭から簡単に説明すると

df1

OriginIDDestinationIDShape_Length
1A10
2B15
3A5

df2

OriginIDDestinationIDShape_Length
AX100
AY50
BZ30

df1df2DestinationID列とOriginID列の値でマージ(how='outer')

OriginID_1stDestinationID_1stShape_Length_1stOriginID_2ndDestinationID_2ndShape_Length_2nd
1A10AX100
1A10AY50
3A5AX100
3A5AY50
2B15BZ30

トータルの距離を計算しTotal列を追加

OriginID_1stDestinationID_1stShape_Length_1stOriginID_2ndDestinationID_2ndShape_Length_2ndTotal
1A10AX100110
1A10AY5060
3A5AX100105
3A5AY5055
2B15BZ3045

Total列が最小の行を抽出

df['Total'].idxmin() にて Total列が最小の行のIndex値が得られる

OriginID_1stDestinationID_1stShape_Length_1stOriginID_2ndDestinationID_2ndShape_Length_2ndTotal
2B15BZ3045

という処理となります


【追記】
2番目に小さい距離を求める方法と

2番めに小さい距離を求めるには、idxmin() のような関数は使えませんので、一度 DataFrameを Totalの大きさによってソート(DataFrame.sort_values()してから、そのデータフレームの2行目を取得するとよいと思います。)

Python

1import pandas as pd 2 3df1 = pd.DataFrame([[1,'A',10],[2,'B',15],[3,'A',5]], 4 columns=['OriginID','DestinationID','Shape_Length']) 5 6df2 = pd.DataFrame([['A','X',100],['A','Y',50],['B','Z',30]], 7 columns=['OriginID','DestinationID','Shape_Length']) 8 9df = pd.merge(df1, df2, left_on='DestinationID', right_on='OriginID', how='outer', suffixes=('_1st', '_2nd')) 10df['Total'] = df['Shape_Length_1st'] + df['Shape_Length_2nd'] 11 12# Totalにてソート(昇順) 13sorted_df = df.sort_values('Total') 14print(sorted_df) 15# 2行目(2番目に小さい値)を取得 16second_row = sorted_df.iloc[1] 17print(f"2番目に小さい値は{second_row['Total']}であり、この時の経路は {second_row['OriginID_1st']} - {second_row['DestinationID_1st']} - {second_row['DestinationID_2nd']}") 18# 2番目に小さい値は55であり、この時の経路は 3 - A - Y

投稿2019/10/21 01:46

編集2019/10/23 00:11
magichan

総合スコア15898

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/10/21 02:49

ご丁寧に教えていただきありがとうございます。ここで使用したcsvファイルは数が少なくpd.DataFrame([[1,'A',10],[2,'B',15],[3,'A',5]], columns=['OriginID','DestinationID','Shape_Length']) のようにすべて書き出すことが可能かと思いますが、csvのデータが1000など大きくなった場合, filename = pd.read_csv('OD(1).csv', encoding="SHIFT-JIS")のようにcsvファイルを指定してあげればよいのでしょうか? 初歩的なことをお聞きし、申し訳ございません。 よろしくお願いいたします。
magichan

2019/10/21 03:22

はいその通りです。 今回はCSVデータを使う場合は pd.read_csv() にて読み込みます。(その場合、CSVデータの1行目が列名として扱われます。) 行数が多くても基本的に行うことは同じですので、 df = pd.read_csv(...) のようにCSVを読み込んだあと print(df) のようにデータの内容を表示して、データの内容を確認ながら処理を行うと良いかと思います。
退会済みユーザー

退会済みユーザー

2019/10/21 05:39

ご返信ありがとうございます。 お忙しい中、ご丁寧な対応ありがとうございました。
退会済みユーザー

退会済みユーザー

2019/10/21 23:23

お忙しいところ申し訳ございません。 もう一点よろしいでしょうか。 今回は最小値を求めるスクリプトでしたが、2番目に小さい値、3番目に小さい値・・・・となった場合にはどのように変更すればよろしいでしょうか。(DestinationID_1stとOrigin_ID2stが同じであれば、OrijinIDが今回(OrijinID:2)と異なるものでも結構です。) =教えていただいた図でいうTotal:55を出力したいです。 よろしくお願いいたします。
magichan

2019/10/23 00:11

追記しました
退会済みユーザー

退会済みユーザー

2019/10/23 05:54

お忙しいところ、ありがとうございます。 教えていた内容で解決いたしました。
guest

0

そもそもminを求めたい場合、forで回さず、argminを利用した方が良いです。
そしてやりたい事は、以下のような感じでしょうか。

python

1import pandas as pd 2import numpy as np 3 4df = pd.DataFrame([[1,'A',10],[2,'B',15],[3,'A',5]]) 5df2 = pd.DataFrame([['A','X',100],['A','Y',50],['B','Z',30]]) 6print(df) 7print(df2) 8 9idx = np.argmin(df2.iloc[:,2].values) 10print(idx) 11 12v = df2.iloc[idx] 13print(v[0]) 14key = v[0] 15 16v = df.iloc[:,1] 17v = df[df.iloc[:,1]==key] 18print(v) 19

投稿2019/10/18 10:51

t_obara

総合スコア5488

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問